diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index d9f4906f8..4886c7426 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1336,7 +1336,7 @@ UT_004_13: - ESP32_IDF - UT_T1_1 - psram - + UT_005_01: <<: *unit_test_template tags: @@ -1522,6 +1522,20 @@ UT_012_03: - UT_T1_1 - 8Mpsram +UT_012_04: + <<: *unit_test_template + tags: + - ESP32_IDF + - UT_T1_1 + - 8Mpsram + +UT_012_05: + <<: *unit_test_template + tags: + - ESP32_IDF + - UT_T1_1 + - 8Mpsram + UT_601_01: <<: *unit_test_template tags: diff --git a/components/driver/include/driver/spi_common.h b/components/driver/include/driver/spi_common.h index 1dae920a5..b2a6c082e 100644 --- a/components/driver/include/driver/spi_common.h +++ b/components/driver/include/driver/spi_common.h @@ -96,9 +96,32 @@ typedef struct { * Call this if your driver wants to manage a SPI peripheral. * * @param host Peripheral to claim + * @param source The caller indentification string. + * * @return True if peripheral is claimed successfully; false if peripheral already is claimed. */ -bool spicommon_periph_claim(spi_host_device_t host); +bool spicommon_periph_claim(spi_host_device_t host, const char* source); + +// The macro is to keep the back-compatibility of IDF v3.2 and before +// In this way we can call spicommon_periph_claim with two arguments, or the host with the source set to the calling function name +// When two arguments (host, func) are given, __spicommon_periph_claim2 is called +// or if only one arguments (host) is given, __spicommon_periph_claim1 is called +#define spicommon_periph_claim(host...) __spicommon_periph_claim(host, 2, 1) +#define __spicommon_periph_claim(host, source, n, ...) __spicommon_periph_claim ## n(host, source) +#define __spicommon_periph_claim1(host, _) ({ \ + char* warning_str = "calling spicommon_periph_claim without source string is deprecated.";\ + spicommon_periph_claim(host, __FUNCTION__); }) + +#define __spicommon_periph_claim2(host, func) spicommon_periph_claim(host, func) + +/** + * @brief Check whether the spi periph is in use. + * + * @param host Peripheral to check. + * + * @return True if in use, otherwise false. + */ +bool spicommon_periph_in_use(spi_host_device_t host); /** * @brief Return the SPI peripheral so another driver can claim it. @@ -119,6 +142,15 @@ bool spicommon_periph_free(spi_host_device_t host); */ bool spicommon_dma_chan_claim(int dma_chan); +/** + * @brief Check whether the spi DMA channel is in use. + * + * @param dma_chan DMA channel to check. + * + * @return True if in use, otherwise false. + */ +bool spicommon_dma_chan_in_use(int dma_chan); + /** * @brief Return the SPI DMA channel so other driver can claim it, or just to power down DMA. * diff --git a/components/driver/spi_common.c b/components/driver/spi_common.c index fbaabaa73..675ad5ca9 100644 --- a/components/driver/spi_common.c +++ b/components/driver/spi_common.c @@ -52,19 +52,30 @@ typedef struct spi_device_t spi_device_t; //Periph 1 is 'claimed' by SPI flash code. static atomic_bool spi_periph_claimed[3] = { ATOMIC_VAR_INIT(true), ATOMIC_VAR_INIT(false), ATOMIC_VAR_INIT(false)}; +static const char* spi_claiming_func[3] = {NULL, NULL, NULL}; static uint8_t spi_dma_chan_enabled = 0; static portMUX_TYPE spi_dma_spinlock = portMUX_INITIALIZER_UNLOCKED; //Returns true if this peripheral is successfully claimed, false if otherwise. -bool spicommon_periph_claim(spi_host_device_t host) +bool spicommon_periph_claim(spi_host_device_t host, const char* source) { bool false_var = false; bool ret = atomic_compare_exchange_strong(&spi_periph_claimed[host], &false_var, true); - if (ret) periph_module_enable(spi_periph_signal[host].module); + if (ret) { + spi_claiming_func[host] = source; + periph_module_enable(spi_periph_signal[host].module); + } else { + ESP_EARLY_LOGE(SPI_TAG, "SPI%d already claimed by %s.", host+1, spi_claiming_func[host]); + } return ret; } +bool spicommon_periph_in_use(spi_host_device_t host) +{ + return atomic_load(&spi_periph_claimed[host]); +} + //Returns true if this peripheral is successfully freed, false if otherwise. bool spicommon_periph_free(spi_host_device_t host) { @@ -102,6 +113,12 @@ bool spicommon_dma_chan_claim (int dma_chan) return ret; } +bool spicommon_dma_chan_in_use(int dma_chan) +{ + assert(dma_chan==1 || dma_chan == 2); + return spi_dma_chan_enabled & DMA_CHANNEL_ENABLED(dma_chan); +} + bool spicommon_dma_chan_free(int dma_chan) { assert( dma_chan == 1 || dma_chan == 2 ); @@ -190,7 +207,7 @@ esp_err_t spicommon_bus_initialize_io(spi_host_device_t host, const spi_bus_conf if (use_iomux) { //All SPI iomux pin selections resolve to 1, so we put that here instead of trying to figure //out which FUNC_GPIOx_xSPIxx to grab; they all are defined to 1 anyway. - ESP_LOGD(SPI_TAG, "SPI%d use iomux pins.", host ); + ESP_LOGD(SPI_TAG, "SPI%d use iomux pins.", host+1); if (bus_config->mosi_io_num >= 0) { gpio_iomux_in(bus_config->mosi_io_num, spi_periph_signal[host].spid_in); gpio_iomux_out(bus_config->mosi_io_num, FUNC_SPI, false); @@ -214,7 +231,7 @@ esp_err_t spicommon_bus_initialize_io(spi_host_device_t host, const spi_bus_conf temp_flag |= SPICOMMON_BUSFLAG_NATIVE_PINS; } else { //Use GPIO matrix - ESP_LOGD(SPI_TAG, "SPI%d use gpio matrix.", host ); + ESP_LOGD(SPI_TAG, "SPI%d use gpio matrix.", host+1); if (bus_config->mosi_io_num >= 0) { if (mosi_output || (temp_flag&SPICOMMON_BUSFLAG_DUAL)) { gpio_set_direction(bus_config->mosi_io_num, GPIO_MODE_INPUT_OUTPUT); diff --git a/components/driver/spi_master.c b/components/driver/spi_master.c index 95eaa60a7..a29182592 100644 --- a/components/driver/spi_master.c +++ b/components/driver/spi_master.c @@ -234,7 +234,7 @@ esp_err_t spi_bus_initialize(spi_host_device_t host, const spi_bus_config_t *bus SPI_CHECK(host>=SPI_HOST && host<=VSPI_HOST, "invalid host", ESP_ERR_INVALID_ARG); SPI_CHECK( dma_chan >= 0 && dma_chan <= 2, "invalid dma channel", ESP_ERR_INVALID_ARG ); - spi_chan_claimed=spicommon_periph_claim(host); + spi_chan_claimed=spicommon_periph_claim(host, "spi master"); SPI_CHECK(spi_chan_claimed, "host already in use", ESP_ERR_INVALID_STATE); if ( dma_chan != 0 ) { @@ -498,7 +498,7 @@ Specify ``SPI_DEVICE_NO_DUMMY`` to ignore this checking. Then you can output dat spihost[host]->hw->ctrl2.mosi_delay_mode = 0; spihost[host]->hw->ctrl2.mosi_delay_num = 0; *handle=dev; - ESP_LOGD(SPI_TAG, "SPI%d: New device added to CS%d, effective clock: %dkHz", host, freecs, dev->clk_cfg.eff_clk/1000); + ESP_LOGD(SPI_TAG, "SPI%d: New device added to CS%d, effective clock: %dkHz", host+1, freecs, dev->clk_cfg.eff_clk/1000); return ESP_OK; nomem: diff --git a/components/driver/spi_slave.c b/components/driver/spi_slave.c index 5d3026dc6..ddc7ac273 100644 --- a/components/driver/spi_slave.c +++ b/components/driver/spi_slave.c @@ -110,7 +110,7 @@ esp_err_t spi_slave_initialize(spi_host_device_t host, const spi_bus_config_t *b SPI_CHECK(VALID_HOST(host), "invalid host", ESP_ERR_INVALID_ARG); SPI_CHECK( dma_chan >= 0 && dma_chan <= 2, "invalid dma channel", ESP_ERR_INVALID_ARG ); - spi_chan_claimed=spicommon_periph_claim(host); + spi_chan_claimed=spicommon_periph_claim(host, "spi slave"); SPI_CHECK(spi_chan_claimed, "host already in use", ESP_ERR_INVALID_STATE); if ( dma_chan != 0 ) { diff --git a/components/esp32/Kconfig b/components/esp32/Kconfig index edfea9c5a..b71528b3e 100644 --- a/components/esp32/Kconfig +++ b/components/esp32/Kconfig @@ -24,7 +24,7 @@ config SPIRAM_SUPPORT bool "Support for external, SPI-connected RAM" default "n" help - This enables support for an external SPI RAM chip, connected in parallel with the + This enables support for an external SPI RAM chip, connected in parallel with the main SPI flash chip. menu "SPI RAM config" @@ -98,9 +98,10 @@ choice SPIRAM_SPEED 2. Flash SPI running at 80Mhz and RAM SPI running at 40Mhz 3. Flash SPI running at 80Mhz and RAM SPI running at 80Mhz - Note: If the third mode(80Mhz+80Mhz) is enabled, the VSPI port will be occupied by the system. - Application code should never touch VSPI hardware in this case. The option to select - 80MHz will only be visible if the flash SPI speed is also 80MHz. (ESPTOOLPY_FLASHFREQ_80M is true) + Note: If the third mode(80Mhz+80Mhz) is enabled for SPI RAM of type 32MBit, one of the HSPI/VSPI host will + be occupied by the system. Which SPI host to use can be selected by the config item SPIRAM_OCCUPY_SPI_HOST. + Application code should never touch HSPI/VSPI hardware in this case. The option to select + 80MHz will only be visible if the flash SPI speed is also 80MHz. (ESPTOOLPY_FLASHFREQ_80M is true) config SPIRAM_SPEED_40M bool "40MHz clock speed" @@ -125,7 +126,7 @@ config SPIRAM_CACHE_WORKAROUND Revision 1 of the ESP32 has a bug that can cause a write to PSRAM not to take place in some situations when the cache line needs to be fetched from external RAM and an interrupt occurs. This enables a fix in the compiler that makes sure the specific code that is vulnerable to this will not be emitted. - + This will also not use any bits of newlib that are located in ROM, opting for a version that is compiled with the workaround and located in flash instead. @@ -146,9 +147,9 @@ config SPIRAM_BANKSWITCH_RESERVE default 8 range 1 62 help - Select the amount of banks reserved for bank switching. Note that the amount of RAM allocatable with + Select the amount of banks reserved for bank switching. Note that the amount of RAM allocatable with malloc/esp_heap_alloc_caps will decrease by 32K for each page reserved here. - + Note that this reservation is only actually done if your program actually uses the himem API. Without any himem calls, the reservation is not done and the original amount of memory will be available to malloc/esp_heap_alloc_caps. @@ -163,7 +164,7 @@ config SPIRAM_MALLOC_ALWAYSINTERNAL than this size in internal memory, while allocations larger than this will be done from external RAM. If allocation from the preferred region fails, an attempt is made to allocate from the non-preferred region instead, so malloc() will not suddenly fail when either internal or external memory is full. - + config WIFI_LWIP_ALLOCATION_FROM_SPIRAM_FIRST bool "Try to allocate memories of WiFi and LWIP in SPIRAM firstly. If failed, allocate internal memory" depends on SPIRAM_USE_CAPS_ALLOC || SPIRAM_USE_MALLOC @@ -179,12 +180,12 @@ config SPIRAM_MALLOC_RESERVE_INTERNAL help Because the external/internal RAM allocation strategy is not always perfect, it sometimes may happen that the internal memory is entirely filled up. This causes allocations that are specifically done in - internal memory, for example the stack for new tasks or memory to service DMA or have memory that's - also available when SPI cache is down, to fail. This option reserves a pool specifically for requests + internal memory, for example the stack for new tasks or memory to service DMA or have memory that's + also available when SPI cache is down, to fail. This option reserves a pool specifically for requests like that; the memory in this pool is not given out when a normal malloc() is called. - + Set this to 0 to disable this feature. - + Note that because FreeRTOS stacks are forced to internal memory, they will also use this memory pool; be sure to keep this in mind when adjusting this value. @@ -211,7 +212,21 @@ config SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY help If enabled the option,and add EXT_RAM_ATTR defined your variable,then your variable will be placed in PSRAM instead of internal memory, and placed most of variables of lwip,net802.11,pp,bluedroid library - to external memory defaultly. + to external memory defaultly. + +choice SPIRAM_OCCUPY_SPI_HOST + prompt "SPI host to use for 32MBit PSRAM" + default SPIRAM_OCCUPY_VSPI_HOST + depends on SPIRAM_SPEED_80M + help + When both flash and PSRAM is working under 80MHz, and the PSRAM is of type 32MBit, one of the HSPI/VSPI + host will be used to output the clock. Select which one to use here. + +config SPIRAM_OCCUPY_HSPI_HOST + bool "HSPI host (SPI2)" +config SPIRAM_OCCUPY_VSPI_HOST + bool "VSPI host (SPI3)" +endchoice endmenu @@ -257,8 +272,8 @@ choice ESP32_COREDUMP_TO_FLASH_OR_UART help Select place to store core dump: flash, uart or none (to disable core dumps generation). - If core dump is configured to be stored in flash and custom partition table is used add - corresponding entry to your CSV. For examples, please see predefined partition table CSV descriptions + If core dump is configured to be stored in flash and custom partition table is used add + corresponding entry to your CSV. For examples, please see predefined partition table CSV descriptions in the components/partition_table directory. config ESP32_ENABLE_COREDUMP_TO_FLASH @@ -297,18 +312,18 @@ choice NUMBER_OF_UNIVERSAL_MAC_ADDRESS default FOUR_UNIVERSAL_MAC_ADDRESS help Configure the number of universally administered (by IEEE) MAC addresses. - During initialisation, MAC addresses for each network interface are generated or derived from a + During initialisation, MAC addresses for each network interface are generated or derived from a single base MAC address. - If the number of universal MAC addresses is four, all four interfaces (WiFi station, WiFi softap, - Bluetooth and Ethernet) receive a universally administered MAC address. These are generated + If the number of universal MAC addresses is four, all four interfaces (WiFi station, WiFi softap, + Bluetooth and Ethernet) receive a universally administered MAC address. These are generated sequentially by adding 0, 1, 2 and 3 (respectively) to the final octet of the base MAC address. - If the number of universal MAC addresses is two, only two interfaces (WiFi station and Bluetooth) - receive a universally administered MAC address. These are generated sequentially by adding 0 - and 1 (respectively) to the base MAC address. The remaining two interfaces (WiFi softap and Ethernet) - receive local MAC addresses. These are derived from the universal WiFi station and Bluetooth MAC + If the number of universal MAC addresses is two, only two interfaces (WiFi station and Bluetooth) + receive a universally administered MAC address. These are generated sequentially by adding 0 + and 1 (respectively) to the base MAC address. The remaining two interfaces (WiFi softap and Ethernet) + receive local MAC addresses. These are derived from the universal WiFi station and Bluetooth MAC addresses, respectively. - When using the default (Espressif-assigned) base MAC address, either setting can be used. When using - a custom universal MAC address range, the correct setting will depend on the allocation of MAC + When using the default (Espressif-assigned) base MAC address, either setting can be used. When using + a custom universal MAC address range, the correct setting will depend on the allocation of MAC addresses in this range (either 2 or 4 per device.) config TWO_UNIVERSAL_MAC_ADDRESS @@ -318,7 +333,7 @@ config FOUR_UNIVERSAL_MAC_ADDRESS endchoice config NUMBER_OF_UNIVERSAL_MAC_ADDRESS - int + int default 2 if TWO_UNIVERSAL_MAC_ADDRESS default 4 if FOUR_UNIVERSAL_MAC_ADDRESS @@ -366,10 +381,10 @@ config TIMER_TASK_STACK_SIZE to dispatch callbacks of timers created using ets_timer and esp_timer APIs. If you are seing stack overflow errors in timer task, increase this value. - + Note that this is not the same as FreeRTOS timer task. To configure FreeRTOS timer task size, see "FreeRTOS timer task stack size" option - in "FreeRTOS" menu. + in "FreeRTOS" menu. choice NEWLIB_STDOUT_LINE_ENDING prompt "Line ending for UART output" @@ -378,15 +393,15 @@ choice NEWLIB_STDOUT_LINE_ENDING This option allows configuring the desired line endings sent to UART when a newline ('\n', LF) appears on stdout. Three options are possible: - + CRLF: whenever LF is encountered, prepend it with CR - + LF: no modification is applied, stdout is sent as is - + CR: each occurence of LF is replaced with CR - + This option doesn't affect behavior of the UART driver (drivers/uart.h). - + config NEWLIB_STDOUT_LINE_ENDING_CRLF bool "CRLF" config NEWLIB_STDOUT_LINE_ENDING_LF @@ -402,15 +417,15 @@ choice NEWLIB_STDIN_LINE_ENDING This option allows configuring which input sequence on UART produces a newline ('\n', LF) on stdin. Three options are possible: - + CRLF: CRLF is converted to LF - + LF: no modification is applied, input is sent to stdin as is - + CR: each occurence of CR is replaced with LF - + This option doesn't affect behavior of the UART driver (drivers/uart.h). - + config NEWLIB_STDIN_LINE_ENDING_CRLF bool "CRLF" config NEWLIB_STDIN_LINE_ENDING_LF @@ -445,7 +460,7 @@ choice CONSOLE_UART default CONSOLE_UART_DEFAULT help Select whether to use UART for console output (through stdout and stderr). - + - Default is to use UART0 on pins GPIO1(TX) and GPIO3(RX). - If "Custom" is selected, UART0 or UART1 can be chosen, and any pins can be selected. @@ -559,10 +574,10 @@ config ESP32_DEBUG_OCDAWARE config ESP32_DEBUG_STUBS_ENABLE bool "OpenOCD debug stubs" - default OPTIMIZATION_LEVEL_DEBUG + default OPTIMIZATION_LEVEL_DEBUG depends on !ESP32_TRAX help - Debug stubs are used by OpenOCD to execute pre-compiled onboard code which does some useful debugging, + Debug stubs are used by OpenOCD to execute pre-compiled onboard code which does some useful debugging, e.g. GCOV data dump. config INT_WDT @@ -596,7 +611,7 @@ config TASK_WDT help The Task Watchdog Timer can be used to make sure individual tasks are still running. Enabling this option will cause the Task Watchdog Timer to be - initialized automatically at startup. The Task Watchdog timer can be + initialized automatically at startup. The Task Watchdog timer can be initialized after startup as well (see Task Watchdog Timer API Reference) config TASK_WDT_PANIC @@ -710,7 +725,7 @@ choice ESP32_TIME_SYSCALL continue in deep sleep. Time will be reported at 1 microsecond resolution. This is the default, and the recommended option. - If only high-resolution timer is used, gettimeofday will - provide time at microsecond resolution. + provide time at microsecond resolution. Time will not be preserved when going into deep sleep mode. - If only RTC timer is used, timekeeping will continue in deep sleep, but time will be measured at 6.(6) microsecond @@ -736,7 +751,7 @@ choice ESP32_RTC_CLOCK_SOURCE default ESP32_RTC_CLOCK_SOURCE_INTERNAL_RC help Choose which clock is used as RTC clock source. - + - "Internal 150kHz oscillator" option provides lowest deep sleep current consumption, and does not require extra external components. However frequency stability with respect to temperature is poor, so time may @@ -752,7 +767,7 @@ choice ESP32_RTC_CLOCK_SOURCE ground. 32K_XN pin can not be used as a GPIO in this case. - "Internal 8.5MHz oscillator divided by 256" option results in higher deep sleep current (by 5uA) but has better frequency stability than - the internal 150kHz oscillator. It does not require external components. + the internal 150kHz oscillator. It does not require external components. config ESP32_RTC_CLOCK_SOURCE_INTERNAL_RC bool "Internal 150kHz RC oscillator" @@ -777,7 +792,7 @@ config ESP32_RTC_CLK_CAL_CYCLES by the calibration routine. Higher numbers increase calibration precision, which may be important for applications which spend a lot of time in deep sleep. Lower numbers reduce startup time. - + When this option is set to 0, clock calibration will not be performed at startup, and approximate clock frequencies will be assumed: @@ -792,15 +807,15 @@ config ESP32_RTC_XTAL_BOOTSTRAP_CYCLES default 5 range 0 32768 help - To reduce the startup time of an external RTC crystal, - we bootstrap it with a 32kHz square wave for a fixed number of cycles. - Setting 0 will disable bootstrapping (if disabled, the crystal may take + To reduce the startup time of an external RTC crystal, + we bootstrap it with a 32kHz square wave for a fixed number of cycles. + Setting 0 will disable bootstrapping (if disabled, the crystal may take longer to start up or fail to oscillate under some conditions). - - If this value is too high, a faulty crystal may initially start and then fail. + + If this value is too high, a faulty crystal may initially start and then fail. If this value is too low, an otherwise good crystal may not start. - - To accurately determine if the crystal has started, + + To accurately determine if the crystal has started, set a larger "Number of cycles for RTC_SLOW_CLK calibration" (about 3000). config ESP32_DEEP_SLEEP_WAKEUP_DELAY @@ -814,9 +829,9 @@ config ESP32_DEEP_SLEEP_WAKEUP_DELAY time to pass between power on and first read operation. By default, without any extra delay, this time is approximately 900us, although some flash chip types need more than that. - + By default extra delay is set to 2000us. When optimizing startup time - for applications which require it, this value may be reduced. + for applications which require it, this value may be reduced. If you are seeing "flash read err, 1000" message printed to the console after deep sleep reset, try increasing this value. @@ -915,7 +930,7 @@ config ESP32_RTCDATA_IN_FAST_MEM help This option allows to place .rtc_data and .rtc_rodata sections into RTC fast memory segment to free the slow memory region for ULP programs. - This option depends on the CONFIG_FREERTOS_UNICORE option because RTC fast memory + This option depends on the CONFIG_FREERTOS_UNICORE option because RTC fast memory can be accessed only by PRO_CPU core. endmenu # ESP32-Specific @@ -1052,8 +1067,8 @@ config ESP32_WIFI_CSI_ENABLED bool "WiFi CSI(Channel State Information)" default n help - Select this option to enable CSI(Channel State Information) feature. CSI takes about - CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM KB of RAM. If CSI is not used, it is better to disable + Select this option to enable CSI(Channel State Information) feature. CSI takes about + CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM KB of RAM. If CSI is not used, it is better to disable this feature in order to save memory. config ESP32_WIFI_AMPDU_TX_ENABLED @@ -1070,7 +1085,7 @@ config ESP32_WIFI_TX_BA_WIN default 6 help Set the size of WiFi Block Ack TX window. Generally a bigger value means higher throughput but - more memory. Most of time we should NOT change the default value unless special reason, e.g. + more memory. Most of time we should NOT change the default value unless special reason, e.g. test the maximum UDP TX throughput with iperf etc. For iperf test in shieldbox, the recommended value is 9~12. @@ -1086,8 +1101,8 @@ config ESP32_WIFI_RX_BA_WIN range 2 32 default 6 help - Set the size of WiFi Block Ack RX window. Generally a bigger value means higher throughput but - more memory. Most of time we should NOT change the default value unless special reason, e.g. + Set the size of WiFi Block Ack RX window. Generally a bigger value means higher throughput but + more memory. Most of time we should NOT change the default value unless special reason, e.g. test the maximum UDP RX throughput with iperf etc. For iperf test in shieldbox, the recommended value is 9~12. @@ -1118,17 +1133,17 @@ config ESP32_WIFI_SOFTAP_BEACON_MAX_LEN ESP-MESH utilizes beacon frames to detect and resolve root node conflicts (see documentation). However the default length of a beacon frame can simultaneously hold only five root node identifier structures, meaning that a root node conflict of up to five nodes can be detected at one time. In the occurence of more root nodes conflict involving more - than five root nodes, the conflict resolution process will detect five of the root nodes, resolve the conflict, and + than five root nodes, the conflict resolution process will detect five of the root nodes, resolve the conflict, and re-detect more root nodes. This process will repeat until all root node conflicts are resolved. However this process can generally take a very long time. - + To counter this situation, the beacon frame length can be increased such that more root nodes can be detected simultaneously. Each additional root node will require 36 bytes and should be added ontop of the default beacon frame length of - 752 bytes. For example, if you want to detect 10 root nodes simultaneously, you need to set the beacon frame length as + 752 bytes. For example, if you want to detect 10 root nodes simultaneously, you need to set the beacon frame length as 932 (752+36*5). - + Setting a longer beacon length also assists with debugging as the conflicting root nodes can be identified more quickly. - + endmenu # Wi-Fi menu PHY @@ -1139,7 +1154,7 @@ config ESP32_PHY_CALIBRATION_AND_DATA_STORAGE help If this option is enabled, NVS will be initialized and calibration data will be loaded from there. PHY calibration will be skipped on deep sleep wakeup. If calibration data is not found, full calibration - will be performed and stored in NVS. Normally, only partial calibration will be performed. + will be performed and stored in NVS. Normally, only partial calibration will be performed. If this option is disabled, full calibration will be performed. If it's easy that your board calibrate bad data, choose 'n'. @@ -1163,7 +1178,7 @@ config ESP32_PHY_INIT_DATA_IN_PARTITION into the application binary. If unsure, choose 'n'. - + config ESP32_PHY_MAX_WIFI_TX_POWER int "Max WiFi TX power (dBm)" range 0 20 @@ -1189,7 +1204,7 @@ config PM_ENABLE This option has run-time overhead (increased interrupt latency, longer time to enter idle state), and it also reduces accuracy of RTOS ticks and timers used for timekeeping. - Enable this option if application uses power management APIs. + Enable this option if application uses power management APIs. config PM_DFS_INIT_AUTO bool "Enable dynamic frequency scaling (DFS) at startup" @@ -1226,7 +1241,7 @@ config PM_PROFILING This feature can be used to analyze which locks are preventing the chip from going into a lower power state, and see what time the chip spends in each power saving mode. This feature does incur some run-time - overhead, so should typically be disabled in production builds. + overhead, so should typically be disabled in production builds. config PM_TRACE bool "Enable debug tracing of PM using GPIOs" @@ -1239,6 +1254,6 @@ config PM_TRACE This feature is intended to be used when analyzing/debugging behavior of power management implementation, and should be kept disabled in applications. - + endmenu # "Power Management" diff --git a/components/esp32/clk.c b/components/esp32/clk.c index 9e30121fc..5825a1865 100644 --- a/components/esp32/clk.c +++ b/components/esp32/clk.c @@ -32,6 +32,7 @@ #include "driver/periph_ctrl.h" #include "xtensa/core-macros.h" #include "bootloader_clock.h" +#include "driver/spi_common.h" /* Number of cycles to wait from the 32k XTAL oscillator to consider it running. * Larger values increase startup delay. Smaller values may cause false positive @@ -131,10 +132,10 @@ void esp_clk_init(void) // Wait for UART TX to finish, otherwise some UART output will be lost // when switching APB frequency uart_tx_wait_idle(CONFIG_CONSOLE_UART_NUM); - + rtc_clk_cpu_freq_set_config(&new_config); - // Re calculate the ccount to make time calculation correct. + // Re calculate the ccount to make time calculation correct. XTHAL_SET_CCOUNT( XTHAL_GET_CCOUNT() * new_freq_mhz / old_freq_mhz ); } @@ -292,11 +293,16 @@ void esp_perip_clk_init(void) DPORT_SPI_DMA_CLK_EN; #if CONFIG_SPIRAM_SPEED_80M -//80MHz SPIRAM uses SPI3 as well; it's initialized before this is called. Because it is used in +//80MHz SPIRAM uses SPI2/SPI3 as well; it's initialized before this is called. Because it is used in //a weird mode where clock to the peripheral is disabled but reset is also disabled, it 'hangs' //in a state where it outputs a continuous 80MHz signal. Mask its bit here because we should //not modify that state, regardless of what we calculated earlier. - common_perip_clk &= ~DPORT_SPI3_CLK_EN; + if (!spicommon_periph_in_use(HSPI_HOST)) { + common_perip_clk &= ~DPORT_SPI2_CLK_EN; + } + if (!spicommon_periph_in_use(VSPI_HOST)) { + common_perip_clk &= ~DPORT_SPI3_CLK_EN; + } #endif /* Change I2S clock to audio PLL first. Because if I2S uses 160MHz clock, diff --git a/components/esp32/spiram_psram.c b/components/esp32/spiram_psram.c index 3a1b7fb27..4bef607da 100644 --- a/components/esp32/spiram_psram.c +++ b/components/esp32/spiram_psram.c @@ -98,6 +98,27 @@ typedef enum { #define _SPI_80M_CLK_DIV 1 #define _SPI_40M_CLK_DIV 2 +//For 4MB PSRAM, we need one more SPI host, select which one to use by kconfig +#ifdef CONFIG_SPIRAM_OCCUPY_HSPI_HOST +#define PSRAM_SPI_MODULE PERIPH_HSPI_MODULE +#define PSRAM_SPI_HOST HSPI_HOST +#define PSRAM_CLK_SIGNAL HSPICLK_OUT_IDX +#define PSRAM_SPI_NUM PSRAM_SPI_2 +#define PSRAM_SPICLKEN DPORT_SPI2_CLK_EN +#elif defined CONFIG_SPIRAM_OCCUPY_VSPI_HOST +#define PSRAM_SPI_MODULE PERIPH_VSPI_MODULE +#define PSRAM_SPI_HOST VSPI_HOST +#define PSRAM_CLK_SIGNAL VSPICLK_OUT_IDX +#define PSRAM_SPI_NUM PSRAM_SPI_3 +#define PSRAM_SPICLKEN DPORT_SPI3_CLK_EN +#else //set to SPI avoid HSPI and VSPI being used +#define PSRAM_SPI_MODULE PERIPH_SPI_MODULE +#define PSRAM_SPI_HOST SPI_HOST +#define PSRAM_CLK_SIGNAL SPICLK_OUT_IDX +#define PSRAM_SPI_NUM PSRAM_SPI_1 +#define PSRAM_SPICLKEN DPORT_SPI01_CLK_EN +#endif + static const char* TAG = "psram"; typedef enum { PSRAM_SPI_1 = 0x1, @@ -566,9 +587,9 @@ esp_err_t IRAM_ATTR psram_enable(psram_cache_mode_t mode, psram_vaddr_mode_t vad CLEAR_PERI_REG_MASK(SPI_USER_REG(PSRAM_SPI_1), SPI_CS_HOLD); gpio_matrix_out(PSRAM_CS_IO, SPICS1_OUT_IDX, 0, 0); /* We need to delay CLK to the PSRAM with respect to the clock signal as output by the SPI peripheral. - We do this by routing it signal to signal 224/225, which are used as a loopback; the extra run through - the GPIO matrix causes the delay. We use GPIO20 (which is not in any package but has pad logic in - silicon) as a temporary pad for this. So the signal path is: + We do this by routing it signal to signal 224/225, which are used as a loopback; the extra run through + the GPIO matrix causes the delay. We use GPIO20 (which is not in any package but has pad logic in + silicon) as a temporary pad for this. So the signal path is: SPI CLK --> GPIO28 --> signal224(in then out) --> internal GPIO29 --> signal225(in then out) --> GPIO17(PSRAM CLK) */ gpio_matrix_out(PSRAM_INTERNAL_IO_28, SPICLK_OUT_IDX, 0, 0); @@ -621,27 +642,27 @@ esp_err_t IRAM_ATTR psram_enable(psram_cache_mode_t mode, psram_vaddr_mode_t vad } else if (PSRAM_IS_32MBIT_VER0(s_psram_id)) { s_clk_mode = PSRAM_CLK_MODE_DCLK; if (mode == PSRAM_CACHE_F80M_S80M) { - /* note: If the third mode(80Mhz+80Mhz) is enabled for 32MBit 1V8 psram, VSPI port will be - occupied by the system. - Application code should never touch VSPI hardware in this case. We try to stop applications + /* note: If the third mode(80Mhz+80Mhz) is enabled for 32MBit 1V8 psram, one of HSPI/VSPI port will be + occupied by the system (according to kconfig). + Application code should never touch HSPI/VSPI hardware in this case. We try to stop applications from doing this using the drivers by claiming the port for ourselves */ - periph_module_enable(PERIPH_VSPI_MODULE); - bool r=spicommon_periph_claim(VSPI_HOST); + periph_module_enable(PSRAM_SPI_MODULE); + bool r=spicommon_periph_claim(PSRAM_SPI_HOST, "psram"); if (!r) { return ESP_ERR_INVALID_STATE; } - gpio_matrix_out(PSRAM_CLK_IO, VSPICLK_OUT_IDX, 0, 0); + gpio_matrix_out(PSRAM_CLK_IO, PSRAM_CLK_SIGNAL, 0, 0); //use spi3 clock,but use spi1 data/cs wires //We get a solid 80MHz clock from SPI3 by setting it up, starting a transaction, waiting until it //is in progress, then cutting the clock (but not the reset!) to that peripheral. - WRITE_PERI_REG(SPI_ADDR_REG(PSRAM_SPI_3), 32 << 24); - WRITE_PERI_REG(SPI_CLOCK_REG(PSRAM_SPI_3), SPI_CLK_EQU_SYSCLK_M); //SET 80M AND CLEAR OTHERS - SET_PERI_REG_MASK(SPI_CMD_REG(PSRAM_SPI_3), SPI_FLASH_READ_M); + WRITE_PERI_REG(SPI_ADDR_REG(PSRAM_SPI_NUM), 32 << 24); + WRITE_PERI_REG(SPI_CLOCK_REG(PSRAM_SPI_NUM), SPI_CLK_EQU_SYSCLK_M); //SET 80M AND CLEAR OTHERS + SET_PERI_REG_MASK(SPI_CMD_REG(PSRAM_SPI_NUM), SPI_FLASH_READ_M); uint32_t spi_status; while (1) { - spi_status = READ_PERI_REG(SPI_EXT2_REG(PSRAM_SPI_3)); + spi_status = READ_PERI_REG(SPI_EXT2_REG(PSRAM_SPI_NUM)); if (spi_status != 0 && spi_status != 1) { - DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI3_CLK_EN); + DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, PSRAM_SPICLKEN); break; } } diff --git a/components/esp32/test/CMakeLists.txt b/components/esp32/test/CMakeLists.txt index 3c6373fb9..baaa34309 100644 --- a/components/esp32/test/CMakeLists.txt +++ b/components/esp32/test/CMakeLists.txt @@ -1,30 +1,38 @@ -set(COMPONENT_SRCDIRS ".") -set(COMPONENT_ADD_INCLUDEDIRS ". ${CMAKE_CURRENT_BINARY_DIR}") +if (CONFIG_TEST_ESP32_SUBTEST_ONLY) + set(COMPONENT_SRCDIRS "psram_4m") + set(COMPONENT_ADD_INCLUDEDIRS ".") -set(COMPONENT_REQUIRES unity nvs_flash ulp) + register_component() -register_component() +else() + set(COMPONENT_SRCDIRS ". psram_4m") + set(COMPONENT_ADD_INCLUDEDIRS ". ${CMAKE_CURRENT_BINARY_DIR}") -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_PATH} - DEPENDS "${CMAKE_CURRENT_LIST_DIR}/logo.jpg") + set(COMPONENT_REQUIRES unity nvs_flash ulp) -# Calculate MD5 value of header file esp_wifi_os_adapter.h -execute_process(COMMAND md5sum ${IDF_PATH}/components/esp32/include/esp_wifi_os_adapter.h - COMMAND cut -c 1-7 - OUTPUT_VARIABLE WIFI_OS_ADAPTER_MD5 - OUTPUT_STRIP_TRAILING_WHITESPACE) + register_component() -# Calculate MD5 value of header file esp_wifi_crypto_types.h -execute_process(COMMAND md5sum ${IDF_PATH}/components/esp32/include/esp_wifi_crypto_types.h - COMMAND cut -c 1-7 - OUTPUT_VARIABLE WIFI_CRYPTO_MD5 - OUTPUT_STRIP_TRAILING_WHITESPACE) + 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_PATH} + DEPENDS "${CMAKE_CURRENT_LIST_DIR}/logo.jpg") -add_definitions(-DWIFI_OS_ADAPTER_MD5=\"${WIFI_OS_ADAPTER_MD5}\") -add_definitions(-DWIFI_CRYPTO_MD5=\"${WIFI_CRYPTO_MD5}\") + # Calculate MD5 value of header file esp_wifi_os_adapter.h + execute_process(COMMAND md5sum ${IDF_PATH}/components/esp32/include/esp_wifi_os_adapter.h + COMMAND cut -c 1-7 + OUTPUT_VARIABLE WIFI_OS_ADAPTER_MD5 + OUTPUT_STRIP_TRAILING_WHITESPACE) -add_custom_target(esp32_test_logo DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/test_tjpgd_logo.h") + # Calculate MD5 value of header file esp_wifi_crypto_types.h + execute_process(COMMAND md5sum ${IDF_PATH}/components/esp32/include/esp_wifi_crypto_types.h + COMMAND cut -c 1-7 + OUTPUT_VARIABLE WIFI_CRYPTO_MD5 + OUTPUT_STRIP_TRAILING_WHITESPACE) -add_dependencies(${COMPONENT_NAME} esp32_test_logo) \ No newline at end of file + add_definitions(-DWIFI_OS_ADAPTER_MD5=\"${WIFI_OS_ADAPTER_MD5}\") + add_definitions(-DWIFI_CRYPTO_MD5=\"${WIFI_CRYPTO_MD5}\") + + add_custom_target(esp32_test_logo DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/test_tjpgd_logo.h") + + add_dependencies(${COMPONENT_NAME} esp32_test_logo) +endif() \ No newline at end of file diff --git a/components/esp32/test/component.mk b/components/esp32/test/component.mk index 592b9b904..41947b1b7 100644 --- a/components/esp32/test/component.mk +++ b/components/esp32/test/component.mk @@ -6,7 +6,11 @@ COMPONENT_EXTRA_CLEAN := test_tjpgd_logo.h COMPONENT_ADD_LDFLAGS = -Wl,--whole-archive -l$(COMPONENT_NAME) -Wl,--no-whole-archive -COMPONENT_SRCDIRS := . test_vectors +ifdef CONFIG_TEST_ESP32_SUBTEST_ONLY +COMPONENT_SRCDIRS := psram_4m +else +COMPONENT_SRCDIRS := . test_vectors psram_4m +endif # Calculate MD5 value of header file esp_wifi_os_adapter.h WIFI_OS_ADAPTER_MD5_VAL=\"$(shell md5sum $(IDF_PATH)/components/esp32/include/esp_wifi_os_adapter.h | cut -c 1-7)\" diff --git a/components/esp32/test/psram_4m/test_4mpsram.c b/components/esp32/test/psram_4m/test_4mpsram.c new file mode 100644 index 000000000..29aef654e --- /dev/null +++ b/components/esp32/test/psram_4m/test_4mpsram.c @@ -0,0 +1,69 @@ +#include "esp_heap_caps.h" +#include "unity.h" +#include "esp_log.h" +#include "driver/spi_common.h" + +static const char TAG[] = "test_psram"; + +static void test_psram_content() +{ + const int test_size = 2048; + uint32_t *test_area = heap_caps_malloc(test_size, MALLOC_CAP_SPIRAM); + + size_t p; + size_t s=test_size; + int errct=0; + int initial_err=-1; + for (p=0; p<(s/sizeof(int)); p+=4) { + test_area[p]=p^0xAAAAAAAA; + } + for (p=0; p<(s/sizeof(int)); p+=4) { + if (test_area[p]!=(p^0xAAAAAAAA)) { + errct++; + if (errct==1) initial_err=p*4; + } + } + if (errct) { + ESP_LOGE(TAG, "SPI SRAM memory test fail. %d/%d writes failed, first @ %p\n", errct, s/32, initial_err+test_area); + TEST_FAIL(); + } else { + ESP_LOGI(TAG, "SPI SRAM memory test OK"); + } + + free(test_area); +} + +// NOTE: this unit test rely on the config that PSRAM of 8MB is used only when CONFIG_SPIRAM_BNKSWITCH_ENABLE is set +TEST_CASE("can use spi when not being used by psram", "[esp32]") +{ + spi_host_device_t host; +#if !CONFIG_SPIRAM_SUPPORT || !CONFIG_SPIRAM_SPEED_80M || CONFIG_SPIRAM_BANKSWITCH_ENABLE + //currently all 8M psram don't need more SPI peripherals + host = -1; +#elif CONFIG_SPIRAM_OCCUPY_HSPI_HOST + host = HSPI_HOST; +#elif CONFIG_SPIRAM_OCCUPY_VSPI_HOST + host = VSPI_HOST; +#endif + + bool claim_hspi = spicommon_periph_claim(HSPI_HOST, "ut-hspi"); + if (claim_hspi) ESP_LOGI(TAG, "HSPI claimed."); + + bool claim_vspi = spicommon_periph_claim(VSPI_HOST, "ut-vspi"); + if (claim_vspi) ESP_LOGI(TAG, "VSPI claimed."); + + if (host == HSPI_HOST) { + TEST_ASSERT(claim_hspi==false); + TEST_ASSERT(claim_vspi==true); + } else if (host == VSPI_HOST) { + TEST_ASSERT(claim_vspi==false); + TEST_ASSERT(claim_hspi==true); + } else { + TEST_ASSERT(claim_hspi==true); + TEST_ASSERT(claim_vspi==true); + } + +#ifdef CONFIG_SPIRAM_SUPPORT + test_psram_content(); +#endif +} diff --git a/docs/en/api-guides/external-ram.rst b/docs/en/api-guides/external-ram.rst index 860bc4f35..a596ee23e 100644 --- a/docs/en/api-guides/external-ram.rst +++ b/docs/en/api-guides/external-ram.rst @@ -7,8 +7,8 @@ Support for external RAM Introduction ============ -The ESP32 has a few hundred KiB of internal RAM, residing on the same die as the rest of the ESP32. For some purposes, this is insufficient, -and therefore the ESP32 incorporates the ability to also use up to 4MiB of external SPI RAM memory as memory. The external memory is incorporated +The ESP32 has a few hundred KiB of internal RAM, residing on the same die as the rest of the ESP32. For some purposes, this is insufficient, +and therefore the ESP32 incorporates the ability to also use up to 4MiB of external SPI RAM memory as memory. The external memory is incorporated in the memory map and is, within certain restrictions, usable in the same way internal data RAM is. Hardware @@ -17,7 +17,7 @@ Hardware The ESP32 supports SPI (P)SRAM connected in parallel with the SPI flash chip. While the ESP32 is capable of supporting several types of RAM chips, the ESP32 SDK at the moment only supports the ESP-PSRAM32 chip. -The ESP-PSRAM32 chip is an 1.8V device, and can only be used in parallel with an 1.8V flash part. Make sure to either set the MTDI +The ESP-PSRAM32 chip is an 1.8V device, and can only be used in parallel with an 1.8V flash part. Make sure to either set the MTDI pin to a high signal level on bootup, or program the fuses in the ESP32 to always use a VDD_SIO level of 1.8V. Not doing this risks damaging the PSRAM and/or flash chip. @@ -47,8 +47,8 @@ ESP-IDF fully supports integrating external memory use into your applications. E * Initialize RAM, add it to the capability allocator and add memory to the pool of RAM that can be returned by ``malloc()``. This allows any application to use the external RAM without having to rewrite the code to use ``heap_caps_malloc``. * Initialize RAM, use a region start from 0x3F800000 for storing zero initialized data(BSS segment) of lwip,net802.11,pp,bluedroid library - by enabling :ref: `CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY` in menuconfig,this way can save some internal memory,because the BSS segment - originally stored in internal memory,and the rest of external RAM can be add the capability allocator and add memory to the pool of RAM as above way + by enabling :ref: `CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY` in menuconfig, this way can save some internal memory,because the BSS segment + originally stored in internal memory,and the rest of external RAM can be add the capability allocator and add memory to the pool of RAM as above way All these options can be selected from the menuconfig menu. @@ -62,19 +62,20 @@ The use of external RAM has a few restrictions: * External RAM cannot be used as a place to store DMA transaction descriptors or as a buffer for a DMA transfer to read from or write into. Any buffers that will be used in combination with DMA must be allocated using ``heap_caps_malloc(size, MALLOC_CAP_DMA)`` (and can be freed using a standard ``free()`` call.) - * External RAM uses the same cache region as the external flash. This means that often accessed variables in external RAM can be read and - modified almost as quickly as in internal ram. However, when accessing large chunks of data (>32K), the cache can be insufficient and speeds - will fall back to the access speed of the external RAM. Moreover, accessing large chunks of data can 'push out' cached flash, possibly making + * External RAM uses the same cache region as the external flash. This means that often accessed variables in external RAM can be read and + modified almost as quickly as in internal ram. However, when accessing large chunks of data (>32K), the cache can be insufficient and speeds + will fall back to the access speed of the external RAM. Moreover, accessing large chunks of data can 'push out' cached flash, possibly making execution of code afterwards slower. * External RAM cannot be used as task stack memory; because of this, xTaskCreate and similar functions will always allocate internal memory for stack and task TCBs and xTaskCreateStatic-type functions will check if the buffers passed are internal. However, for tasks not calling on code in ROM in any way, directly or indirectly, the menuconfig option :ref:`CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY` will eliminate the check in xTaskCreateStatic, allowing task stack in external RAM. Using this is not advised, however. * External RAM initialized failed can not be ignored if enabled :ref:`CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY`; because of this, some BSS segment - can not be placed into external memory if PSRAM can't work normally and can not be moved to internal memory at runtime because the address of + can not be placed into external memory if PSRAM can't work normally and can not be moved to internal memory at runtime because the address of them is defined by linkfile, the :ref:`CONFIG_SPIRAM_IGNORE_NOTFOUND` can't handle this situation,if you want to enable :ref: - `CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY` the :ref:`CONFIG_SPIRAM_IGNORE_NOTFOUND` will be disabled, and if initialize SPIRAM failed,the system + `CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY` the :ref:`CONFIG_SPIRAM_IGNORE_NOTFOUND` will be disabled, and if initialize SPIRAM failed,the system will invoke abort. + * External RAM of 4MBit (test up to know) has to be used with one of HSPI/VSPI occupied under 80MHz. Select which SPI host to be used by :ref:`CONFIG_SPIRAM_OCCUPY_SPI_HOST`. Because there are a fair few situations that have a specific need for internal memory, but it is also possible to use malloc() to exhaust internal memory, there is a pool reserved specifically for requests that cannot be resolved from external memory; allocating task @@ -85,7 +86,7 @@ in menuconfig. Chip revisions ============== -There are some issues with certain revisions of the ESP32 that have repercussions for use with external RAM. These are documented in the ESP32 +There are some issues with certain revisions of the ESP32 that have repercussions for use with external RAM. These are documented in the ESP32 ECO_ document. In particular, ESP-IDF handles the bugs mentioned in the following ways: ESP32 rev v0 @@ -94,8 +95,8 @@ ESP-IDF has no workaround for the bugs in this revision of silicon, and it canno ESP32 rev v1 ------------ -The bugs in this silicon revision introduce a hazard when certain sequences of machine instructions operate on external memory locations (ESP32 ECO 3.2). -To work around this, the gcc compiler to compile ESP-IDF has been expanded with a flag: ``-mfix-esp32-psram-cache-issue``. With this flag passed to gcc +The bugs in this silicon revision introduce a hazard when certain sequences of machine instructions operate on external memory locations (ESP32 ECO 3.2). +To work around this, the gcc compiler to compile ESP-IDF has been expanded with a flag: ``-mfix-esp32-psram-cache-issue``. With this flag passed to gcc on the command line, the compiler works around these sequences and only outputs code that can safely be executed. In ESP-IDF, this flag is enabled when you select :ref:`CONFIG_SPIRAM_CACHE_WORKAROUND`. ESP-IDF also takes other measures to make diff --git a/tools/unit-test-app/components/unity/Kconfig b/tools/unit-test-app/components/unity/Kconfig index 642d76f9d..02ffde126 100644 --- a/tools/unit-test-app/components/unity/Kconfig +++ b/tools/unit-test-app/components/unity/Kconfig @@ -13,3 +13,14 @@ config UNITY_FREERTOS_STACK_SIZE default 8192 endmenu + +menu "Test options" + +config TEST_ESP32_SUBTEST_ONLY + bool "Test only 4M PSRAM cases for esp32 component" + depends on SPIRAM_SUPPORT + default n + help + If this option is enabled, only 4M PSRAM cases are compiled. Otherwise all cases are included. + +endmenu diff --git a/tools/unit-test-app/configs/psram_hspi b/tools/unit-test-app/configs/psram_hspi new file mode 100644 index 000000000..1e4583c1f --- /dev/null +++ b/tools/unit-test-app/configs/psram_hspi @@ -0,0 +1,6 @@ +TEST_COMPONENTS=esp32 +CONFIG_TEST_ESP32_SUBTEST_ONLY=y +CONFIG_ESPTOOLPY_FLASHFREQ_80M=y +CONFIG_SPIRAM_SUPPORT=y +CONFIG_SPIRAM_SPEED_80M=y +CONFIG_SPIRAM_OCCUPY_HSPI_HOST=y diff --git a/tools/unit-test-app/configs/psram_vspi b/tools/unit-test-app/configs/psram_vspi new file mode 100644 index 000000000..73bbd4868 --- /dev/null +++ b/tools/unit-test-app/configs/psram_vspi @@ -0,0 +1,6 @@ +TEST_COMPONENTS=esp32 +CONFIG_TEST_ESP32_SUBTEST_ONLY=y +CONFIG_ESPTOOLPY_FLASHFREQ_80M=y +CONFIG_SPIRAM_SUPPORT=y +CONFIG_SPIRAM_SPEED_80M=y +CONFIG_SPIRAM_OCCUPY_VSPI_HOST=y