mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
Merge branch 'bugfix/esp32s2beta_cache_spiflash_test' into 'feature/esp32s2beta'
util-test: The cache and spi_flash tests passed See merge request espressif/esp-idf!5363
This commit is contained in:
commit
7e81e3da89
19
components/esp32s2beta/test/CMakeLists.txt
Normal file
19
components/esp32s2beta/test/CMakeLists.txt
Normal file
@ -0,0 +1,19 @@
|
||||
if(IDF_TARGET STREQUAL "esp32s2beta")
|
||||
idf_component_register(SRC_DIRS .
|
||||
INCLUDE_DIRS . ${CMAKE_CURRENT_BINARY_DIR}
|
||||
REQUIRES unity test_utils nvs_flash ulp esp_common
|
||||
)
|
||||
|
||||
add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/test_tjpgd_logo.h"
|
||||
COMMAND xxd -i "logo.jpg" "${CMAKE_CURRENT_BINARY_DIR}/test_tjpgd_logo.h"
|
||||
WORKING_DIRECTORY ${COMPONENT_DIR}
|
||||
DEPENDS "${CMAKE_CURRENT_LIST_DIR}/logo.jpg")
|
||||
|
||||
add_custom_target(esp32s2beta_test_logo DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/test_tjpgd_logo.h")
|
||||
|
||||
add_dependencies(${COMPONENT_LIB} esp32s2beta_test_logo)
|
||||
|
||||
idf_build_set_property(COMPILE_DEFINITIONS "-DESP_TIMER_DYNAMIC_OVERFLOW_VAL" APPEND)
|
||||
target_link_libraries(${COMPONENT_LIB} INTERFACE "-u ld_include_test_dport_xt_highint5")
|
||||
endif()
|
||||
|
4
components/esp32s2beta/test/component.mk
Normal file
4
components/esp32s2beta/test/component.mk
Normal file
@ -0,0 +1,4 @@
|
||||
#
|
||||
# Component Makefile
|
||||
#
|
||||
COMPONENT_CONFIG_ONLY := 1
|
BIN
components/esp32s2beta/test/logo.jpg
Normal file
BIN
components/esp32s2beta/test/logo.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 7.4 KiB |
185
components/esp32s2beta/test/test_libgcc.c
Normal file
185
components/esp32s2beta/test/test_libgcc.c
Normal file
@ -0,0 +1,185 @@
|
||||
#include <complex.h>
|
||||
#include "unity.h"
|
||||
|
||||
TEST_CASE("libgcc math functions", "[rom]")
|
||||
{
|
||||
extern int64_t __absvdi2(int64_t x);
|
||||
TEST_ASSERT(__absvdi2(-1L) == 1);
|
||||
extern int __absvsi2(int x);
|
||||
TEST_ASSERT(__absvsi2(-1) == 1);
|
||||
extern double __adddf3(double x, double y);
|
||||
TEST_ASSERT(__adddf3(1.0, 4.0) == 5.0);
|
||||
extern float __addsf3(float x, float y);
|
||||
TEST_ASSERT(__addsf3(1.0f, 4.0f) == 5.0f);
|
||||
extern int64_t __addvdi3(int64_t x, int64_t y);
|
||||
TEST_ASSERT(__addvdi3(1L, 4L) == 5L);
|
||||
extern int __addvsi3(int x, int y);
|
||||
TEST_ASSERT(__addvsi3(1, 4) == 5);
|
||||
extern int64_t __ashldi3(int64_t x, int y);
|
||||
TEST_ASSERT(__ashldi3(1, 4) == 16);
|
||||
extern int64_t __ashrdi3(int64_t x, int y);
|
||||
TEST_ASSERT(__ashrdi3(4, 1) == 2);
|
||||
extern int64_t __bswapdi2(int64_t x);
|
||||
TEST_ASSERT(__bswapdi2(0xaabbccddeeff0011ULL) == 0x1100ffeeddccbbaaULL);
|
||||
extern int32_t __bswapsi2(int32_t x);
|
||||
TEST_ASSERT(__bswapsi2(0xaabbccdd) == 0xddccbbaa);
|
||||
extern int64_t __clrsbdi2(int64_t x);
|
||||
TEST_ASSERT(__clrsbdi2(-1) == 63);
|
||||
extern int __clrsbsi2(int x);
|
||||
TEST_ASSERT(__clrsbsi2(-1) == 31);
|
||||
extern int __clzdi2(int64_t x);
|
||||
TEST_ASSERT(__clzdi2(1) == 63);
|
||||
extern int __clzsi2(int x);
|
||||
TEST_ASSERT(__clzsi2(1) == 31);
|
||||
extern int __cmpdi2(int64_t x, int64_t y);
|
||||
TEST_ASSERT(__cmpdi2(10, 10) == 1);
|
||||
extern int __ctzdi2(uint64_t x);
|
||||
TEST_ASSERT(__ctzdi2(0x8000000000000000ULL) == 63);
|
||||
extern int __ctzsi2(unsigned x);
|
||||
TEST_ASSERT(__ctzsi2(0x80000000U) == 31);
|
||||
extern complex double __divdc3(double a, double b, double c, double d);
|
||||
TEST_ASSERT(__divdc3(0, 1, 1, 0) == I);
|
||||
extern double __divdf3(double x, double y);
|
||||
TEST_ASSERT(__divdf3(16.0, 2.0) == 8.0);
|
||||
extern int64_t __divdi3(int64_t x, int64_t y);
|
||||
TEST_ASSERT(__divdi3(16, 2) == 8);
|
||||
extern complex float __divsc3(float a, float b, float c, float d);
|
||||
TEST_ASSERT(__divsc3(0, 1, 1, 0) == I);
|
||||
extern float __divsf3(float x, float y);
|
||||
TEST_ASSERT(__divsf3(16.0f, 2.0f) == 8.0f);
|
||||
extern int __divsi3(int x, int y);
|
||||
TEST_ASSERT(__divsi3(16, 2) == 8);
|
||||
extern int __eqdf2(double x, double y);
|
||||
TEST_ASSERT(__eqdf2(4.0, 4.0) == 0);
|
||||
extern int __eqsf2(float x, float y);
|
||||
TEST_ASSERT(__eqsf2(4.0f, 4.0f) == 0);
|
||||
extern double __extendsfdf2(float x);
|
||||
TEST_ASSERT(__extendsfdf2(4.0f) == 4.0);
|
||||
extern int __ffsdi2(uint64_t x);
|
||||
TEST_ASSERT(__ffsdi2(0x8000000000000000ULL) == 64);
|
||||
extern int __ffssi2(unsigned x);
|
||||
TEST_ASSERT(__ffssi2(0x80000000) == 32);
|
||||
extern int64_t __fixdfdi(double x);
|
||||
TEST_ASSERT(__fixdfdi(4.0) == 4LL);
|
||||
extern int __fixdfsi(double x);
|
||||
TEST_ASSERT(__fixdfsi(4.0) == 4);
|
||||
extern int64_t __fixsfdi(float x);
|
||||
TEST_ASSERT(__fixsfdi(4.0f) == 4LL);
|
||||
extern int __fixsfsi(float x);
|
||||
TEST_ASSERT(__fixsfsi(4.0f) == 4);
|
||||
extern unsigned __fixunsdfsi(double x);
|
||||
TEST_ASSERT(__fixunsdfsi(16.0) == 16);
|
||||
extern uint64_t __fixunssfdi(float x);
|
||||
TEST_ASSERT(__fixunssfdi(16.0f) == 16);
|
||||
extern unsigned __fixunssfsi(float x);
|
||||
TEST_ASSERT(__fixunssfsi(16.0f) == 16);
|
||||
extern double __floatdidf(int64_t);
|
||||
TEST_ASSERT(__floatdidf(-1LL) == -1.0f);
|
||||
extern float __floatdisf(int64_t);
|
||||
TEST_ASSERT(__floatdisf(-1LL) == -1.0f);
|
||||
extern double __floatsidf(int x);
|
||||
TEST_ASSERT(__floatsidf(-1) == -1.0);
|
||||
extern float __floatsisf(int x);
|
||||
TEST_ASSERT(__floatsisf(-1) == -1.0f);
|
||||
extern double __floatundidf(uint64_t x);
|
||||
TEST_ASSERT(__floatundidf(16) == 16.0);
|
||||
extern float __floatundisf(uint64_t x);
|
||||
TEST_ASSERT(__floatundisf(16) == 16.0f);
|
||||
extern double __floatunsidf(unsigned x);
|
||||
TEST_ASSERT(__floatunsidf(16) == 16.0);
|
||||
extern float __floatunsisf(unsigned x);
|
||||
TEST_ASSERT(__floatunsisf(16) == 16.0f);
|
||||
extern int __gedf2(double x, double y);
|
||||
TEST_ASSERT(__gedf2(2.0, 0.0) >= 0);
|
||||
extern int __gesf2(float x, float y);
|
||||
TEST_ASSERT(__gesf2(2.0f, 0.0f) >= 0);
|
||||
extern int __gtdf2(double x, double y);
|
||||
TEST_ASSERT(__gtdf2(2.0, 0.0) >= 0);
|
||||
extern int __gtsf2(float x, float y);
|
||||
TEST_ASSERT(__gtsf2(2.0f, 0.0f) >= 0);
|
||||
extern int __ledf2(double x, double y);
|
||||
TEST_ASSERT(__ledf2(0.0, 2.0) <= 0);
|
||||
extern int __lesf2(float x, float y);
|
||||
TEST_ASSERT(__lesf2(0.0f, 2.0f) <= 0);
|
||||
extern int64_t __lshrdi3(int64_t x, int y);
|
||||
TEST_ASSERT(__lshrdi3(0x8000000000000000LL, 1) == 0x4000000000000000LL);
|
||||
extern int __ltdf2(double x, double y);
|
||||
TEST_ASSERT(__ltdf2(0.0, 2.0) < 0);
|
||||
extern int __ltsf2(float x, float y);
|
||||
TEST_ASSERT(__ltsf2(0.0f, 2.0f) < 0);
|
||||
extern int64_t __moddi3(int64_t x, int64_t y);
|
||||
TEST_ASSERT(__moddi3(15, 2) == 1);
|
||||
extern int __modsi3(int x, int y);
|
||||
TEST_ASSERT(__modsi3(15, 2) == 1);
|
||||
extern complex double __muldc3(double a, double b, double c, double d);
|
||||
TEST_ASSERT(__muldc3(1.0, 0.0, 0.0, 1.0) == I);
|
||||
extern double __muldf3(double x, double y);
|
||||
TEST_ASSERT(__muldf3(2.0, 8.0) == 16.0);
|
||||
extern int64_t __muldi3(int64_t x, int64_t y);
|
||||
TEST_ASSERT(__muldi3(2, 8) == 16);
|
||||
extern complex float __mulsc3 (float a, float b, float c, float d);
|
||||
TEST_ASSERT(__mulsc3(1.0f, 0.0f, 0.0f, -1.0f) == -I);
|
||||
extern float __mulsf3 (float a, float b);
|
||||
TEST_ASSERT(__mulsf3(2.0f, 8.0f) == 16.0f);
|
||||
extern int __mulsi3(int x, int y);
|
||||
TEST_ASSERT(__mulsi3(2, 8) == 16);
|
||||
extern int __mulvdi3(int64_t x, int64_t y);
|
||||
TEST_ASSERT(__mulvdi3(2, 8) == 16);
|
||||
extern int __mulvsi3(int x, int y);
|
||||
TEST_ASSERT(__mulvsi3(2, 8) == 16);
|
||||
extern int __nedf2(double x, double y);
|
||||
TEST_ASSERT(__nedf2(2.0, 2.0) == 0);
|
||||
extern double __negdf2(double x);
|
||||
TEST_ASSERT(__negdf2(1.0) == -1.0);
|
||||
extern int64_t __negdi2(int64_t x);
|
||||
TEST_ASSERT(__negdi2(-1LL) == 1);
|
||||
extern float __negsf2(float x);
|
||||
TEST_ASSERT(__negsf2(-1.0f) == 1.0f);
|
||||
extern int64_t __negvdi2(int64_t x);
|
||||
TEST_ASSERT(__negvdi2(-1LL) == 1);
|
||||
extern int __negvsi2(int x);
|
||||
TEST_ASSERT(__negvsi2(-1) == 1);
|
||||
extern int __nesf2(float x, float y);
|
||||
TEST_ASSERT(__nesf2(2.0, 0.0) != 0);
|
||||
extern int __paritysi2(unsigned x);
|
||||
TEST_ASSERT(__paritysi2(0x10101010) == 0);
|
||||
extern int __popcountdi2(uint64_t);
|
||||
TEST_ASSERT(__popcountdi2(0xaaaaaaaa11111111ULL) == 24);
|
||||
extern int __popcountsi2(unsigned x);
|
||||
TEST_ASSERT(__popcountsi2(0x11111111) == 8);
|
||||
extern double __powidf2(double x, int y);
|
||||
TEST_ASSERT(__powidf2(2.0, -1) == 0.5);
|
||||
extern float __powisf2(float x, int y);
|
||||
TEST_ASSERT(__powisf2(2.0f, 2) == 4.0f);
|
||||
extern double __subdf3(double x, double y);
|
||||
TEST_ASSERT(__subdf3(2.0, 1.0) == 1.0);
|
||||
extern float __subsf3(float x, float y);
|
||||
TEST_ASSERT(__subsf3(5.0f, 4.0f) == 1.0f);
|
||||
extern int64_t __subvdi3(int64_t x, int64_t y);
|
||||
TEST_ASSERT(__subvdi3(-1LL, -1LL) == 0);
|
||||
extern int __subvsi3(int x, int y);
|
||||
TEST_ASSERT(__subvsi3(-1, -1) == 0);
|
||||
extern float __truncdfsf2(double x);
|
||||
TEST_ASSERT(__truncdfsf2(4.0) == 4.0f);
|
||||
extern int __ucmpdi2(uint64_t x, uint64_t y);
|
||||
TEST_ASSERT(__ucmpdi2(0x100000000ULL, 0x100000000ULL) == 1);
|
||||
extern uint64_t __udivdi3(uint64_t x, uint64_t y);
|
||||
TEST_ASSERT(__udivdi3(15, 2) == 7);
|
||||
extern uint64_t __udivmoddi4(uint64_t x, uint64_t y, uint64_t* z);
|
||||
uint64_t z;
|
||||
TEST_ASSERT(__udivmoddi4(15, 2, &z) == 7);
|
||||
TEST_ASSERT(z == 1);
|
||||
extern unsigned __udivsi3(unsigned x, unsigned y);
|
||||
TEST_ASSERT(__udivsi3(15, 2) == 7);
|
||||
extern uint64_t __umoddi3(uint64_t x, uint64_t y);
|
||||
TEST_ASSERT(__umoddi3(15, 2) == 1);
|
||||
extern unsigned __umodsi3(unsigned x, unsigned y);
|
||||
TEST_ASSERT(__umodsi3(15, 2) == 1);
|
||||
extern uint64_t __umulsidi3(unsigned x, unsigned y);
|
||||
TEST_ASSERT(__umulsidi3(0x10000000, 0x10000000) == 0x100000000000000ULL);
|
||||
extern int __unorddf2(double x, double y);
|
||||
TEST_ASSERT(__unorddf2(1.0, 2.0) == 0);
|
||||
extern int __unordsf2(float x, float y);
|
||||
TEST_ASSERT(__unordsf2(2.0f, 1.0f) == 0);
|
||||
|
||||
}
|
182
components/esp32s2beta/test/test_spiram_cache_flush.c
Normal file
182
components/esp32s2beta/test/test_spiram_cache_flush.c
Normal file
@ -0,0 +1,182 @@
|
||||
/*
|
||||
This code tests the interaction between PSRAM and SPI flash routines.
|
||||
*/
|
||||
|
||||
#include <esp_types.h>
|
||||
#include <stdio.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "freertos/queue.h"
|
||||
#include "freertos/xtensa_api.h"
|
||||
#include "unity.h"
|
||||
#include "soc/dport_reg.h"
|
||||
#include "soc/io_mux_reg.h"
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "esp_heap_caps.h"
|
||||
#include "esp_spi_flash.h"
|
||||
#include "esp_partition.h"
|
||||
#include "test_utils.h"
|
||||
|
||||
#if CONFIG_SPIRAM
|
||||
|
||||
#if CONFIG_SPIRAM_USE_CAPS_ALLOC || CONFIG_SPIRAM_USE_MALLOC
|
||||
#define USE_CAPS_ALLOC 1
|
||||
#endif // CONFIG_SPIRAM_USE_CAPS_ALLOC || CONFIG_SPIRAM_USE_MALLOC
|
||||
|
||||
#define TSTSZ (16*1024)
|
||||
|
||||
#if !CONFIG_FREERTOS_UNICORE
|
||||
|
||||
volatile static int res[2], err[2];
|
||||
|
||||
void tstMem(void *arg) {
|
||||
volatile unsigned char *mem=(volatile unsigned char*)arg;
|
||||
int p=0;
|
||||
while(1) {
|
||||
for (int i=0; i<TSTSZ; i++) {
|
||||
mem[i]=(i^p);
|
||||
}
|
||||
for (int i=0; i<TSTSZ; i++) {
|
||||
if (mem[i]!=((i^p)&0xff)) {
|
||||
printf("Core %d mem err! Got %x espected %x at addr %p\n", xPortGetCoreID(), mem[i], (i^p)&0xff, &mem[i]);
|
||||
err[xPortGetCoreID()]++;
|
||||
}
|
||||
}
|
||||
p++;
|
||||
res[xPortGetCoreID()]++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
TEST_CASE("Spiram cache flush on mmap", "[spiram]")
|
||||
{
|
||||
void *mem[2];
|
||||
res[0]=0; res[1]=0;
|
||||
#if USE_CAPS_ALLOC
|
||||
printf("Allocating SPI RAM chunk...\n");
|
||||
mem[0]=heap_caps_malloc(TSTSZ, MALLOC_CAP_SPIRAM);
|
||||
mem[1]=heap_caps_malloc(TSTSZ, MALLOC_CAP_SPIRAM);
|
||||
#else
|
||||
mem[0]=(void*)SOC_EXTRAM_DATA_LOW;
|
||||
mem[1]=(void*)SOC_EXTRAM_DATA_LOW+TSTSZ;
|
||||
#endif
|
||||
assert(mem[0]);
|
||||
assert(mem[1]);
|
||||
TaskHandle_t th[2];
|
||||
err[0]=0; err[1]=0;
|
||||
printf("Creating tasks\n");
|
||||
xTaskCreatePinnedToCore(tstMem , "tskone" , 2048, mem[0], 3, &th[0], 0);
|
||||
xTaskCreatePinnedToCore(tstMem , "tsktwo" , 2048, mem[1], 3, &th[1], 1);
|
||||
|
||||
for (int l=0; l<10; l++) {
|
||||
for (int p=0; p<4096*1024; p+=65536) {
|
||||
const void *out;
|
||||
spi_flash_mmap_handle_t h;
|
||||
spi_flash_mmap(p, 65536, SPI_FLASH_MMAP_DATA, &out, &h);
|
||||
spi_flash_munmap(h);
|
||||
}
|
||||
}
|
||||
|
||||
printf("Checked memory %d and %d times. Errors: %d and %d\n", res[0], res[1], err[0], err[1]);
|
||||
|
||||
vTaskDelete(th[0]);
|
||||
vTaskDelete(th[1]);
|
||||
#if USE_CAPS_ALLOC
|
||||
free(mem[0]);
|
||||
free(mem[1]);
|
||||
#endif
|
||||
TEST_ASSERT(err[0]==0);
|
||||
TEST_ASSERT(err[1]==0);
|
||||
}
|
||||
|
||||
|
||||
#define CYCLES 1024
|
||||
|
||||
TEST_CASE("Spiram cache flush on write/read", "[spiram]")
|
||||
{
|
||||
void *mem[2];
|
||||
res[0]=0; res[1]=0;
|
||||
#if USE_CAPS_ALLOC
|
||||
printf("Allocating SPI RAM chunk...\n");
|
||||
mem[0]=heap_caps_malloc(TSTSZ, MALLOC_CAP_SPIRAM);
|
||||
mem[1]=heap_caps_malloc(TSTSZ, MALLOC_CAP_SPIRAM);
|
||||
#else
|
||||
mem[0]=(void*)SOC_EXTRAM_DATA_LOW;
|
||||
mem[1]=(void*)SOC_EXTRAM_DATA_LOW+TSTSZ;
|
||||
#endif
|
||||
assert(mem[0]);
|
||||
assert(mem[1]);
|
||||
TaskHandle_t th[2];
|
||||
const esp_partition_t* part = get_test_data_partition();
|
||||
assert(part!=NULL);
|
||||
|
||||
printf("Erasing sector...\n");
|
||||
esp_partition_erase_range(part, 0, 64*1024);
|
||||
printf("Erased.\n");
|
||||
printf("Creating tasks\n");
|
||||
xTaskCreatePinnedToCore(tstMem , "tskone" , 2048, mem[0], 3, &th[0], 0);
|
||||
xTaskCreatePinnedToCore(tstMem , "tsktwo" , 2048, mem[1], 3, &th[1], 1);
|
||||
char buf[512];
|
||||
|
||||
const void *out;
|
||||
spi_flash_mmap_handle_t handle;
|
||||
esp_partition_mmap(part, 0, 512, SPI_FLASH_MMAP_DATA, &out, &handle);
|
||||
for (int i=0; i<CYCLES; i++) {
|
||||
esp_partition_write(part, 0, buf, 512);
|
||||
esp_partition_read(part, 0, buf, 512);
|
||||
vTaskDelay(1);
|
||||
}
|
||||
spi_flash_munmap(handle);
|
||||
|
||||
printf("Checked memory %d and %d times.\n", res[0], res[1]);
|
||||
|
||||
vTaskDelete(th[0]);
|
||||
vTaskDelete(th[1]);
|
||||
#if USE_CAPS_ALLOC
|
||||
free(mem[0]);
|
||||
free(mem[1]);
|
||||
#endif
|
||||
}
|
||||
#endif // !CONFIG_FREERTOS_UNICORE
|
||||
|
||||
IRAM_ATTR TEST_CASE("Spiram memcmp weirdness at 80MHz", "[spiram]") {
|
||||
char *mem1=malloc(0x10000);
|
||||
#if USE_CAPS_ALLOC
|
||||
char *mem2=heap_caps_malloc(0x10000, MALLOC_CAP_SPIRAM);
|
||||
#else
|
||||
char *mem2=(void*)SOC_EXTRAM_DATA_LOW;
|
||||
#endif
|
||||
|
||||
#if !CONFIG_SPIRAM_SPEED_80M
|
||||
printf("**** WARNING **** Spi memory isn't running at 80MHz, so this test is somewhat meaningless.\n");
|
||||
#endif
|
||||
|
||||
printf("RAM: Got %p and %p\n", mem1, mem2);
|
||||
assert(mem1);
|
||||
assert(mem2);
|
||||
for (int i=0; i<0x10000; i++) mem1[i]=i^0xAAAAAAAA;
|
||||
|
||||
for (int cycle=1; cycle<100; cycle++) {
|
||||
memcpy(mem2, mem1, 0x10000);
|
||||
if (memcmp(mem1, mem2, 0x10000)!=0) {
|
||||
printf("Memcmp failed! Cycle %d\n", cycle);
|
||||
for (int i=0; i<0x10000; i++) {
|
||||
if (mem1[i]!=mem2[i]) {
|
||||
printf("Found real difference at index %d: 0x%x vs 0x%x\n", i, mem1[i], mem2[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
free(mem1);
|
||||
#if USE_CAPS_ALLOC
|
||||
free(mem2);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif // CONFIG_SPIRAM
|
25
components/esp32s2beta/test/test_stack_check.c
Normal file
25
components/esp32s2beta/test/test_stack_check.c
Normal file
@ -0,0 +1,25 @@
|
||||
#include "unity.h"
|
||||
|
||||
#if CONFIG_COMPILER_STACK_CHECK
|
||||
|
||||
static void recur_and_smash(void)
|
||||
{
|
||||
static int cnt;
|
||||
volatile uint8_t buf[50];
|
||||
volatile int num = sizeof(buf)+10;
|
||||
|
||||
if (cnt++ < 1) {
|
||||
recur_and_smash();
|
||||
}
|
||||
for (int i = 0; i < num; i++) {
|
||||
buf[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
TEST_CASE("stack smashing protection", "[stack_check] [ignore]")
|
||||
{
|
||||
recur_and_smash();
|
||||
}
|
||||
|
||||
#endif
|
25
components/esp32s2beta/test/test_stack_check_cxx.cpp
Normal file
25
components/esp32s2beta/test/test_stack_check_cxx.cpp
Normal file
@ -0,0 +1,25 @@
|
||||
#include "unity.h"
|
||||
|
||||
#if CONFIG_COMPILER_STACK_CHECK
|
||||
|
||||
static void recur_and_smash_cxx(void)
|
||||
{
|
||||
static int cnt;
|
||||
volatile uint8_t buf[50];
|
||||
volatile int num = sizeof(buf)+10;
|
||||
|
||||
if (cnt++ < 1) {
|
||||
recur_and_smash_cxx();
|
||||
}
|
||||
for (int i = 0; i < num; i++) {
|
||||
buf[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
TEST_CASE("stack smashing protection CXX", "[stack_check] [ignore]")
|
||||
{
|
||||
recur_and_smash_cxx();
|
||||
}
|
||||
|
||||
#endif
|
@ -53,12 +53,18 @@
|
||||
#define IROM0_PAGES_END 256
|
||||
#define DROM0_PAGES_START 0
|
||||
#define DROM0_PAGES_END 64
|
||||
|
||||
#define PAGE_IN_FLASH(page) (page)
|
||||
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
#define REGIONS_COUNT 8
|
||||
#define IROM0_PAGES_START (PRO_CACHE_IBUS0_MMU_START / sizeof(uint32_t))
|
||||
#define IROM0_PAGES_END (PRO_CACHE_IBUS2_MMU_END / sizeof(uint32_t))
|
||||
#define DROM0_PAGES_START (Cache_Drom0_Using_ICache()? PRO_CACHE_IBUS3_MMU_START / sizeof(uint32_t) : PRO_CACHE_DBUS3_MMU_START /sizeof(uint32_t))
|
||||
#define DROM0_PAGES_END (Cache_Drom0_Using_ICache()? PRO_CACHE_IBUS3_MMU_END / sizeof(uint32_t) : PRO_CACHE_DBUS3_MMU_END / sizeof(uint32_t))
|
||||
|
||||
#define PAGE_IN_FLASH(page) ((page) | DPORT_MMU_ACCESS_FLASH)
|
||||
|
||||
#endif
|
||||
#define MMU_ADDR_MASK DPORT_MMU_ADDRESS_MASK
|
||||
#define IROM0_PAGES_NUM (IROM0_PAGES_END - IROM0_PAGES_START)
|
||||
@ -86,7 +92,7 @@ static uint32_t s_mmap_last_handle = 0;
|
||||
|
||||
static void IRAM_ATTR spi_flash_mmap_init(void)
|
||||
{
|
||||
if (s_mmap_page_refcnt[0] != 0) {
|
||||
if (s_mmap_page_refcnt[DROM0_PAGES_START] != 0) {
|
||||
return; /* mmap data already initialised */
|
||||
}
|
||||
DPORT_INTERRUPT_DISABLE();
|
||||
@ -148,9 +154,6 @@ esp_err_t IRAM_ATTR spi_flash_mmap(size_t src_addr, size_t size, spi_flash_mmap_
|
||||
}
|
||||
for (int i = 0; i < page_count; i++) {
|
||||
pages[i] = (phys_page+i);
|
||||
#if CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
pages[i] |= DPORT_MMU_ACCESS_FLASH;
|
||||
#endif
|
||||
}
|
||||
ret = spi_flash_mmap_pages(pages, page_count, memory, out_ptr, out_handle);
|
||||
free(pages);
|
||||
@ -169,7 +172,7 @@ esp_err_t IRAM_ATTR spi_flash_mmap_pages(const int *pages, size_t page_count, sp
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
for (int i = 0; i < page_count; i++) {
|
||||
if (pages[i] < 0 || (pages[i] & MMU_ADDR_MASK)*SPI_FLASH_MMU_PAGE_SIZE >= g_rom_flashchip.chip_size) {
|
||||
if (pages[i] < 0 || pages[i]*SPI_FLASH_MMU_PAGE_SIZE >= g_rom_flashchip.chip_size) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
}
|
||||
@ -203,7 +206,7 @@ esp_err_t IRAM_ATTR spi_flash_mmap_pages(const int *pages, size_t page_count, sp
|
||||
for (pos = start; pos < start + page_count; ++pos, ++pageno) {
|
||||
int table_val = (int) DPORT_SEQUENCE_REG_READ((uint32_t)&DPORT_PRO_FLASH_MMU_TABLE[pos]);
|
||||
uint8_t refcnt = s_mmap_page_refcnt[pos];
|
||||
if (refcnt != 0 && table_val != pages[pageno]) {
|
||||
if (refcnt != 0 && table_val != PAGE_IN_FLASH(pages[pageno])) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -229,21 +232,25 @@ esp_err_t IRAM_ATTR spi_flash_mmap_pages(const int *pages, size_t page_count, sp
|
||||
uint32_t entry_app = DPORT_SEQUENCE_REG_READ((uint32_t)&DPORT_APP_FLASH_MMU_TABLE[i]);
|
||||
#endif
|
||||
assert(s_mmap_page_refcnt[i] == 0 ||
|
||||
(entry_pro == pages[pageno]
|
||||
(entry_pro == PAGE_IN_FLASH(pages[pageno])
|
||||
#if !CONFIG_FREERTOS_UNICORE
|
||||
&& entry_app == pages[pageno]
|
||||
&& entry_app == PAGE_IN_FLASH(pages[pageno])
|
||||
#endif
|
||||
));
|
||||
if (s_mmap_page_refcnt[i] == 0) {
|
||||
if (entry_pro != pages[pageno]
|
||||
if (entry_pro != PAGE_IN_FLASH(pages[pageno])
|
||||
#if !CONFIG_FREERTOS_UNICORE
|
||||
|| entry_app != pages[pageno]
|
||||
|| entry_app != PAGE_IN_FLASH(pages[pageno])
|
||||
#endif
|
||||
) {
|
||||
DPORT_PRO_FLASH_MMU_TABLE[i] = pages[pageno];
|
||||
DPORT_PRO_FLASH_MMU_TABLE[i] = PAGE_IN_FLASH(pages[pageno]);
|
||||
#if !CONFIG_FREERTOS_UNICORE
|
||||
DPORT_APP_FLASH_MMU_TABLE[i] = pages[pageno];
|
||||
#endif
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
Cache_Invalidate_Addr(region_addr + (i - region_begin) * SPI_FLASH_MMU_PAGE_SIZE, SPI_FLASH_MMU_PAGE_SIZE);
|
||||
#endif
|
||||
need_flush = true;
|
||||
}
|
||||
}
|
||||
@ -266,22 +273,14 @@ esp_err_t IRAM_ATTR spi_flash_mmap_pages(const int *pages, size_t page_count, sp
|
||||
entire cache.
|
||||
*/
|
||||
if (need_flush) {
|
||||
#if CONFIG_SPIRAM
|
||||
esp_spiram_writeback_cache();
|
||||
#endif
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
# if CONFIG_SPIRAM
|
||||
esp_spiram_writeback_cache();
|
||||
# endif
|
||||
Cache_Flush(0);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
Cache_Invalidate_ICache_All();
|
||||
if (!Cache_Drom0_Using_ICache()) {
|
||||
#if CONFIG_SPIRAM_SUPPORT
|
||||
Cache_WriteBack_All();
|
||||
#endif
|
||||
Cache_Invalidate_DCache_All();
|
||||
}
|
||||
#endif
|
||||
#if !CONFIG_FREERTOS_UNICORE
|
||||
# if !CONFIG_FREERTOS_UNICORE
|
||||
Cache_Flush(1);
|
||||
# endif
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -422,7 +421,7 @@ const void *IRAM_ATTR spi_flash_phys2cache(uint32_t phys_offs, spi_flash_mmap_me
|
||||
spi_flash_disable_interrupts_caches_and_other_cpu();
|
||||
DPORT_INTERRUPT_DISABLE();
|
||||
for (int i = start; i < end; i++) {
|
||||
if (DPORT_SEQUENCE_REG_READ((uint32_t)&DPORT_PRO_FLASH_MMU_TABLE[i]) == phys_page) {
|
||||
if (DPORT_SEQUENCE_REG_READ((uint32_t)&DPORT_PRO_FLASH_MMU_TABLE[i]) == PAGE_IN_FLASH(phys_page)) {
|
||||
i -= page_delta;
|
||||
intptr_t cache_page = base + (SPI_FLASH_MMU_PAGE_SIZE * i);
|
||||
DPORT_INTERRUPT_RESTORE();
|
||||
@ -435,22 +434,31 @@ const void *IRAM_ATTR spi_flash_phys2cache(uint32_t phys_offs, spi_flash_mmap_me
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static bool IRAM_ATTR is_page_mapped_in_cache(uint32_t phys_page)
|
||||
static bool IRAM_ATTR is_page_mapped_in_cache(uint32_t phys_page, const void **out_ptr)
|
||||
{
|
||||
int start[2], end[2];
|
||||
|
||||
*out_ptr = NULL;
|
||||
|
||||
/* SPI_FLASH_MMAP_DATA */
|
||||
start[0] = 0;
|
||||
end[0] = 64;
|
||||
start[0] = DROM0_PAGES_START;
|
||||
end[0] = DROM0_PAGES_END;
|
||||
|
||||
/* SPI_FLASH_MMAP_INST */
|
||||
start[1] = PRO_IRAM0_FIRST_USABLE_PAGE;
|
||||
end[1] = 256;
|
||||
end[1] = IROM0_PAGES_END;
|
||||
|
||||
DPORT_INTERRUPT_DISABLE();
|
||||
for (int j = 0; j < 2; j++) {
|
||||
for (int i = start[j]; i < end[j]; i++) {
|
||||
if (DPORT_SEQUENCE_REG_READ((uint32_t)&DPORT_PRO_FLASH_MMU_TABLE[i]) == phys_page) {
|
||||
if (DPORT_SEQUENCE_REG_READ((uint32_t)&DPORT_PRO_FLASH_MMU_TABLE[i]) == PAGE_IN_FLASH(phys_page)) {
|
||||
#if CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
if (j == 0) { /* SPI_FLASH_MMAP_DATA */
|
||||
*out_ptr = (const void *)(VADDR0_START_ADDR + SPI_FLASH_MMU_PAGE_SIZE * (i - start[0]));
|
||||
} else { /* SPI_FLASH_MMAP_INST */
|
||||
*out_ptr = (const void *)(VADDR1_FIRST_USABLE_ADDR + SPI_FLASH_MMU_PAGE_SIZE * (i - start[1]));
|
||||
}
|
||||
#endif
|
||||
DPORT_INTERRUPT_RESTORE();
|
||||
return true;
|
||||
}
|
||||
@ -463,6 +471,7 @@ static bool IRAM_ATTR is_page_mapped_in_cache(uint32_t phys_page)
|
||||
/* Validates if given flash address has corresponding cache mapping, if yes, flushes cache memories */
|
||||
IRAM_ATTR bool spi_flash_check_and_flush_cache(size_t start_addr, size_t length)
|
||||
{
|
||||
bool ret = false;
|
||||
/* align start_addr & length to full MMU pages */
|
||||
uint32_t page_start_addr = start_addr & ~(SPI_FLASH_MMU_PAGE_SIZE-1);
|
||||
length += (start_addr - page_start_addr);
|
||||
@ -473,7 +482,8 @@ IRAM_ATTR bool spi_flash_check_and_flush_cache(size_t start_addr, size_t length)
|
||||
return false; /* invalid address */
|
||||
}
|
||||
|
||||
if (is_page_mapped_in_cache(page)) {
|
||||
const void *vaddr = NULL;
|
||||
if (is_page_mapped_in_cache(page, &vaddr)) {
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#if CONFIG_SPIRAM
|
||||
esp_spiram_writeback_cache();
|
||||
@ -481,10 +491,16 @@ IRAM_ATTR bool spi_flash_check_and_flush_cache(size_t start_addr, size_t length)
|
||||
Cache_Flush(0);
|
||||
#ifndef CONFIG_FREERTOS_UNICORE
|
||||
Cache_Flush(1);
|
||||
#endif
|
||||
#endif
|
||||
return true;
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
if (vaddr != NULL) {
|
||||
Cache_Invalidate_Addr((uint32_t)vaddr, SPI_FLASH_MMU_PAGE_SIZE);
|
||||
ret = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return ret;
|
||||
}
|
||||
|
@ -73,8 +73,12 @@ TEST_CASE("invalid access to cache raises panic (PRO CPU)", "[spi_flash][ignore]
|
||||
vTaskDelay(1000/portTICK_PERIOD_MS);
|
||||
}
|
||||
|
||||
#ifndef CONFIG_FREERTOS_UNICORE
|
||||
|
||||
TEST_CASE("invalid access to cache raises panic (APP CPU)", "[spi_flash][ignore]")
|
||||
{
|
||||
xTaskCreatePinnedToCore(&cache_access_test_func, "ia", 2048, NULL, 5, NULL, 1);
|
||||
vTaskDelay(1000/portTICK_PERIOD_MS);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -159,15 +159,23 @@ TEST_CASE_ESP32("Can mmap into instruction address space", "[mmap]")
|
||||
printf("Mapping %x (+%x)\n", start - 0x10000, 0x20000);
|
||||
spi_flash_mmap_handle_t handle2;
|
||||
const void *ptr2;
|
||||
ESP_ERROR_CHECK( spi_flash_mmap(start - 0x10000, 0x20000, SPI_FLASH_MMAP_DATA, &ptr2, &handle2) );
|
||||
ESP_ERROR_CHECK( spi_flash_mmap(start - 0x10000, 0x20000, SPI_FLASH_MMAP_INST, &ptr2, &handle2) );
|
||||
printf("mmap_res: handle=%d ptr=%p\n", handle2, ptr2);
|
||||
|
||||
TEST_ASSERT_EQUAL_HEX32(start - 0x10000, spi_flash_cache2phys(ptr2));
|
||||
TEST_ASSERT_EQUAL_PTR(ptr2, spi_flash_phys2cache(start - 0x10000, SPI_FLASH_MMAP_INST));
|
||||
|
||||
spi_flash_mmap_dump();
|
||||
|
||||
printf("Mapping %x (+%x)\n", start, 0x10000);
|
||||
spi_flash_mmap_handle_t handle3;
|
||||
const void *ptr3;
|
||||
ESP_ERROR_CHECK( spi_flash_mmap(start, 0x10000, SPI_FLASH_MMAP_DATA, &ptr3, &handle3) );
|
||||
ESP_ERROR_CHECK( spi_flash_mmap(start, 0x10000, SPI_FLASH_MMAP_INST, &ptr3, &handle3) );
|
||||
printf("mmap_res: handle=%d ptr=%p\n", handle3, ptr3);
|
||||
|
||||
TEST_ASSERT_EQUAL_HEX32(start, spi_flash_cache2phys(ptr3));
|
||||
TEST_ASSERT_EQUAL_PTR(ptr3, spi_flash_phys2cache(start, SPI_FLASH_MMAP_INST));
|
||||
|
||||
spi_flash_mmap_dump();
|
||||
|
||||
printf("Unmapping handle1\n");
|
||||
|
@ -214,10 +214,29 @@ TEST_CASE_ESP32("Test spi_flash_write", "[spi_flash][esp_flash]")
|
||||
* NB: At the moment these only support aligned addresses, because memcpy
|
||||
* is not aware of the 32-but load requirements for these regions.
|
||||
*/
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
#define TEST_SOC_IROM_ADDR (SOC_IROM_LOW)
|
||||
#define TEST_SOC_CACHE_RAM_BANK0_ADDR (SOC_IRAM_LOW)
|
||||
#define TEST_SOC_CACHE_RAM_BANK1_ADDR (SOC_IRAM_LOW + 0x2000)
|
||||
#define TEST_SOC_CACHE_RAM_BANK2_ADDR (SOC_IRAM_LOW + 0x4000)
|
||||
#define TEST_SOC_CACHE_RAM_BANK3_ADDR (SOC_IRAM_LOW + 0x6000)
|
||||
#define TEST_SOC_IRAM_ADDR (SOC_IRAM_LOW + 0x8000)
|
||||
#define TEST_SOC_RTC_IRAM_ADDR (SOC_RTC_IRAM_LOW)
|
||||
#define TEST_SOC_RTC_DRAM_ADDR (SOC_RTC_DRAM_LOW)
|
||||
ESP_ERROR_CHECK(spi_flash_write(start, (char *) TEST_SOC_IROM_ADDR, 16));
|
||||
ESP_ERROR_CHECK(spi_flash_write(start, (char *) TEST_SOC_IRAM_ADDR, 16));
|
||||
ESP_ERROR_CHECK(spi_flash_write(start, (char *) TEST_SOC_CACHE_RAM_BANK0_ADDR, 16));
|
||||
ESP_ERROR_CHECK(spi_flash_write(start, (char *) TEST_SOC_CACHE_RAM_BANK1_ADDR, 16));
|
||||
ESP_ERROR_CHECK(spi_flash_write(start, (char *) TEST_SOC_CACHE_RAM_BANK2_ADDR, 16));
|
||||
ESP_ERROR_CHECK(spi_flash_write(start, (char *) TEST_SOC_CACHE_RAM_BANK3_ADDR, 16));
|
||||
ESP_ERROR_CHECK(spi_flash_write(start, (char *) TEST_SOC_RTC_IRAM_ADDR, 16));
|
||||
ESP_ERROR_CHECK(spi_flash_write(start, (char *) TEST_SOC_RTC_DRAM_ADDR, 16));
|
||||
#else
|
||||
ESP_ERROR_CHECK(spi_flash_write(start, (char *) 0x40000000, 16));
|
||||
ESP_ERROR_CHECK(spi_flash_write(start, (char *) 0x40070000, 16));
|
||||
ESP_ERROR_CHECK(spi_flash_write(start, (char *) 0x40078000, 16));
|
||||
ESP_ERROR_CHECK(spi_flash_write(start, (char *) 0x40080000, 16));
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SPIRAM
|
||||
|
@ -16,11 +16,23 @@ struct flash_test_ctx {
|
||||
SemaphoreHandle_t done;
|
||||
};
|
||||
|
||||
/* Base offset in flash for tests. */
|
||||
static size_t start;
|
||||
|
||||
static void setup_tests(void)
|
||||
{
|
||||
if (start == 0) {
|
||||
const esp_partition_t *part = get_test_data_partition();
|
||||
start = part->address;
|
||||
printf("Test data partition @ 0x%x\n", start);
|
||||
}
|
||||
}
|
||||
|
||||
static void flash_test_task(void *arg)
|
||||
{
|
||||
struct flash_test_ctx *ctx = (struct flash_test_ctx *) arg;
|
||||
vTaskDelay(100 / portTICK_PERIOD_MS);
|
||||
const uint32_t sector = ctx->offset;
|
||||
const uint32_t sector = start / SPI_FLASH_SEC_SIZE + ctx->offset;
|
||||
printf("t%d\n", sector);
|
||||
printf("es%d\n", sector);
|
||||
if (spi_flash_erase_sector(sector) != ESP_OK) {
|
||||
@ -65,13 +77,15 @@ static void flash_test_task(void *arg)
|
||||
|
||||
TEST_CASE("flash write and erase work both on PRO CPU and on APP CPU", "[spi_flash][ignore]")
|
||||
{
|
||||
setup_tests();
|
||||
|
||||
SemaphoreHandle_t done = xSemaphoreCreateCounting(4, 0);
|
||||
struct flash_test_ctx ctx[] = {
|
||||
{ .offset = 0x100 + 6, .done = done },
|
||||
{ .offset = 0x100 + 7, .done = done },
|
||||
{ .offset = 0x100 + 8, .done = done },
|
||||
{ .offset = 0x10 + 6, .done = done },
|
||||
{ .offset = 0x10 + 7, .done = done },
|
||||
{ .offset = 0x10 + 8, .done = done },
|
||||
#ifndef CONFIG_FREERTOS_UNICORE
|
||||
{ .offset = 0x100 + 9, .done = done }
|
||||
{ .offset = 0x10 + 9, .done = done }
|
||||
#endif
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user