mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
Add initial SPI RAM support. This adds support for an ESP-PSRAM32 chip connected to the default flash pins and GPIO 16 and 17. The RAM is mapped to address 0x3F800000, but otherwise ignored by esp-idf as of yet.
This commit is contained in:
parent
518edac42f
commit
34372a091c
@ -8,6 +8,7 @@
|
||||
LINKER_SCRIPTS := \
|
||||
esp32.bootloader.ld \
|
||||
$(IDF_PATH)/components/esp32/ld/esp32.rom.ld \
|
||||
$(IDF_PATH)/components/esp32/ld/esp32.rom.spiram_incompatible_fns.ld \
|
||||
$(IDF_PATH)/components/esp32/ld/esp32.peripherals.ld \
|
||||
esp32.bootloader.rom.ld
|
||||
|
||||
|
@ -27,6 +27,100 @@ config MEMMAP_SMP
|
||||
The ESP32 contains two cores. If you plan to only use one, you can disable this item
|
||||
to save some memory. (ToDo: Make this automatically depend on unicore support)
|
||||
|
||||
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
|
||||
main SPI flash chip.
|
||||
|
||||
menu "SPI RAM config"
|
||||
depends on SPIRAM_SUPPORT
|
||||
|
||||
config SPIRAM_BOOT_INIT
|
||||
bool "Initialize SPI RAM when booting the ESP32"
|
||||
default "y"
|
||||
help
|
||||
If this is enabled, the SPI RAM will be enabled during initial boot. Unless you
|
||||
have specific requirements, you'll want to leave this enabled so memory allocated
|
||||
during boot-up can also be placed in SPI RAM.
|
||||
|
||||
choice SPIRAM_USE
|
||||
prompt "SPI RAM access method"
|
||||
default SPIRAM_USE_MEMMAP
|
||||
help
|
||||
The SPI RAM can be accessed in multiple methods: by just having it available as an unmanaged
|
||||
memory region in the ESP32 memory map, by integrating it in the ESP32s heap as 'special' memory
|
||||
needing heap_caps_malloc to allocate, or by fully integrating it making malloc() also able to
|
||||
return SPI RAM pointers.
|
||||
|
||||
config SPIRAM_USE_MEMMAP
|
||||
bool "Integrate RAM into ESP32 memory map"
|
||||
config SPIRAM_USE_CAPS_ALLOC
|
||||
bool "Make RAM allocatable using heap_caps_malloc(..., MALLOC_CAP_SPISRAM)"
|
||||
depends on TO_BE_DONE
|
||||
config SPIRAM_USE_MALLOC
|
||||
bool "Make RAM allocatable using malloc as well"
|
||||
depends on TO_BE_DONE
|
||||
endchoice
|
||||
|
||||
choice SPIRAM_TYPE
|
||||
prompt "Type of SPI RAM chip in use"
|
||||
default SPIRAM_TYPE_ESPPSRAM32
|
||||
|
||||
config SPIRAM_TYPE_ESPPSRAM32
|
||||
bool "ESP-PSRAM32 or IS25WP032"
|
||||
endchoice
|
||||
|
||||
config SPIRAM_SIZE
|
||||
int
|
||||
default 4194304 if SPIRAM_TYPE_ESPPSRAM32
|
||||
default 0
|
||||
|
||||
choice SPIRAM_SPEED
|
||||
prompt "Set RAM clock speed"
|
||||
default SPIRAM_CACHE_SPEED_40M
|
||||
help
|
||||
Select the speed for the SPI RAM chip.
|
||||
If SPI RAM is enabled, we only support three combinations of SPI speed mode we supported now:
|
||||
|
||||
1. Flash SPI running at 40Mhz and RAM SPI running at 40Mhz
|
||||
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)
|
||||
|
||||
config SPIRAM_SPEED_40M
|
||||
bool "40MHz clock speed"
|
||||
config SPIRAM_SPEED_80M
|
||||
depends on ESPTOOLPY_FLASHFREQ_80M
|
||||
bool "80MHz clock speed"
|
||||
endchoice
|
||||
|
||||
config SPIRAM_MEMTEST
|
||||
bool "Run memory test on SPI RAM initialization"
|
||||
default "y"
|
||||
help
|
||||
Runs a rudimentary memory test on initialization. Aborts when memory test fails. Disable this for
|
||||
slightly faster startop.
|
||||
|
||||
config SPIRAM_CACHE_WORKAROUND
|
||||
bool "Enable workaround for bug in SPI RAM cache for Rev1 ESP32s"
|
||||
depends on SPIRAM_USE_MEMMAP || SPIRAM_USE_CAPS_ALLOC || SPIRAM_USE_MALLOC
|
||||
default "y"
|
||||
help
|
||||
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.
|
||||
|
||||
|
||||
endmenu
|
||||
|
||||
config MEMMAP_TRACEMEM
|
||||
bool
|
||||
default "n"
|
||||
@ -104,16 +198,6 @@ config ESP32_CORE_DUMP_LOG_LEVEL
|
||||
help
|
||||
Config core dump module logging level (0-5).
|
||||
|
||||
# Not implemented and/or needs new silicon rev to work
|
||||
config MEMMAP_SPISRAM
|
||||
bool "Use external SPI SRAM chip as main memory"
|
||||
depends on ESP32_NEEDS_NEW_SILICON_REV
|
||||
default "n"
|
||||
help
|
||||
The ESP32 can control an external SPI SRAM chip, adding the memory it contains to the
|
||||
main memory map. Enable this if you have this hardware and want to use it in the same
|
||||
way as on-chip RAM.
|
||||
|
||||
choice NUMBER_OF_UNIVERSAL_MAC_ADDRESS
|
||||
bool "Number of universally administered (by IEEE) MAC address"
|
||||
default FOUR_UNIVERSAL_MAC_ADDRESS
|
||||
|
@ -30,3 +30,14 @@ all: phy_init_data
|
||||
flash: phy_init_data
|
||||
|
||||
endif # CONFIG_ESP32_PHY_INIT_DATA_IN_PARTITION
|
||||
|
||||
|
||||
# Enable psram cache bug workaround in compiler if selected
|
||||
ifdef CONFIG_SPIRAM_CACHE_WORKAROUND
|
||||
CFLAGS+=-mfix-esp32-psram-cache-issue
|
||||
CXXFLAGS+=-mfix-esp32-psram-cache-issue
|
||||
#Filter out the standard libstdc++ linkage. The component.mk will add a specific
|
||||
#cache-workaround-enabled version.
|
||||
LDFLAGS:=$(filter-out -lstdc++,$(LDFLAGS))
|
||||
endif
|
||||
|
||||
|
@ -7,8 +7,17 @@ ifndef CONFIG_NO_BLOBS
|
||||
LIBS := core rtc net80211 pp wpa smartconfig coexist wps wpa2 phy
|
||||
endif
|
||||
|
||||
#Linker scripts used to link the final application.
|
||||
#Warning: These linker scripts are only used when the normal app is compiled; the bootloader
|
||||
#specifies its own scripts.
|
||||
LINKER_SCRIPTS += esp32.common.ld esp32.rom.ld esp32.peripherals.ld
|
||||
|
||||
#SPI-RAM incompatible functions can be used in when the SPI RAM
|
||||
#workaround is not enabled.
|
||||
ifndef CONFIG_SPIRAM_CACHE_WORKAROUND
|
||||
LINKER_SCRIPTS += esp32.rom.spiram_incompatible_fns.ld
|
||||
endif
|
||||
|
||||
ifeq ("$(CONFIG_NEWLIB_NANO_FORMAT)","y")
|
||||
LINKER_SCRIPTS += esp32.rom.nanofmt.ld
|
||||
endif
|
||||
@ -28,6 +37,11 @@ COMPONENT_ADD_LDFLAGS += $(COMPONENT_PATH)/libhal.a \
|
||||
-u ld_include_panic_highint_hdl \
|
||||
$(addprefix -T ,$(LINKER_SCRIPTS))
|
||||
|
||||
#The cache workaround also needs a c++ standard library recompiled with the workaround.
|
||||
ifdef CONFIG_SPIRAM_CACHE_WORKAROUND
|
||||
COMPONENT_ADD_LDFLAGS += $(COMPONENT_PATH)/libstdcc++-cache-workaround.a
|
||||
endif
|
||||
|
||||
ALL_LIB_FILES := $(patsubst %,$(COMPONENT_PATH)/lib/lib%.a,$(LIBS))
|
||||
|
||||
COMPONENT_SUBMODULES += lib
|
||||
|
@ -63,6 +63,7 @@
|
||||
#include "esp_core_dump.h"
|
||||
#include "esp_app_trace.h"
|
||||
#include "esp_efuse.h"
|
||||
#include "esp_spiram.h"
|
||||
#include "esp_clk.h"
|
||||
#include "esp_timer.h"
|
||||
#include "trax.h"
|
||||
@ -147,6 +148,13 @@ void IRAM_ATTR call_start_cpu0()
|
||||
memset(&_rtc_bss_start, 0, (&_rtc_bss_end - &_rtc_bss_start) * sizeof(_rtc_bss_start));
|
||||
}
|
||||
|
||||
#if CONFIG_SPIRAM_BOOT_INIT
|
||||
if (esp_spiram_init() != ESP_OK) {
|
||||
ESP_EARLY_LOGE(TAG, "Failed to init external RAM!");
|
||||
abort();
|
||||
}
|
||||
#endif
|
||||
|
||||
ESP_EARLY_LOGI(TAG, "Pro cpu up.");
|
||||
|
||||
#if !CONFIG_FREERTOS_UNICORE
|
||||
@ -175,11 +183,23 @@ void IRAM_ATTR call_start_cpu0()
|
||||
DPORT_CLEAR_PERI_REG_MASK(DPORT_APPCPU_CTRL_B_REG, DPORT_APPCPU_CLKGATE_EN);
|
||||
#endif
|
||||
|
||||
|
||||
#if CONFIG_SPIRAM_MEMTEST
|
||||
bool ext_ram_ok=esp_spiram_test();
|
||||
if (!ext_ram_ok) {
|
||||
ESP_EARLY_LOGE(TAG, "External RAM failed memory test!");
|
||||
abort();
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Initialize heap allocator. WARNING: This *needs* to happen *after* the app cpu has booted.
|
||||
If the heap allocator is initialized first, it will put free memory linked list items into
|
||||
memory also used by the ROM. Starting the app cpu will let its ROM initialize that memory,
|
||||
corrupting those linked lists. Initializing the allocator *after* the app cpu has booted
|
||||
works around this problem. */
|
||||
works around this problem.
|
||||
With SPI RAM enabled, there's a second reason: half of the SPI RAM will be managed by the
|
||||
app CPU, and when that is not up yet, the memory will be inaccessible and heap_caps_init may
|
||||
fail initializing it properly. */
|
||||
heap_caps_init();
|
||||
|
||||
ESP_EARLY_LOGI(TAG, "Pro cpu start user code");
|
||||
|
61
components/esp32/include/esp_spiram.h
Normal file
61
components/esp32/include/esp_spiram.h
Normal file
@ -0,0 +1,61 @@
|
||||
// Copyright 2015-2017 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
|
||||
#ifndef __ESP_SPIRAM_H
|
||||
#define __ESP_SPIRAM_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include "esp_err.h"
|
||||
|
||||
/**
|
||||
* @brief Initialize spiram interface/hardware. Normally called from cpu_start.c.
|
||||
*
|
||||
* @return ESP_OK on success
|
||||
*/
|
||||
esp_err_t esp_spiram_init();
|
||||
|
||||
|
||||
/**
|
||||
* @brief Memory test for SPI RAM. Should be called after SPI RAM is initialized and
|
||||
* (in case of a dual-core system) the app CPU is online. This test overwrites the
|
||||
* memory with crap, so do not call after e.g. the heap allocator has stored important
|
||||
* stuff in SPI RAM.
|
||||
*
|
||||
* @return true on success, false on failed memory test
|
||||
*/
|
||||
bool esp_spiram_test();
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the size of the attached SPI RAM chip selected in menuconfig
|
||||
*
|
||||
* @return Size in bytes, or 0 if no external RAM chip support compiled in.
|
||||
*/
|
||||
size_t esp_spiram_get_size();
|
||||
|
||||
|
||||
/**
|
||||
* @brief Force a writeback of the data in the SPI RAM cache. This is to be called whenever
|
||||
* cache is disabled, because disabling cache on the ESP32 discards the data in the SPI
|
||||
* RAM cache.
|
||||
*
|
||||
* This is meant for use from within the SPI flash code.
|
||||
*/
|
||||
void esp_spiram_writeback_cache();
|
||||
|
||||
|
||||
|
||||
#endif
|
@ -4,7 +4,6 @@ Generated for ROM with MD5sum:
|
||||
ab8282ae908fe9e7a63fb2a4ac2df013 ../../rom_image/prorom.elf
|
||||
*/
|
||||
PROVIDE ( abort = 0x4000bba4 );
|
||||
PROVIDE ( abs = 0x40056340 );
|
||||
PROVIDE ( __absvdi2 = 0x4006387c );
|
||||
PROVIDE ( __absvsi2 = 0x40063868 );
|
||||
PROVIDE ( Add2SelfBigHex256 = 0x40015b7c );
|
||||
@ -21,15 +20,8 @@ PROVIDE ( aes_128_cbc_encrypt = 0x4005cc18 );
|
||||
PROVIDE ( aes_unwrap = 0x4005ccf0 );
|
||||
PROVIDE ( app_gpio_arg = 0x3ffe003c );
|
||||
PROVIDE ( app_gpio_handler = 0x3ffe0040 );
|
||||
PROVIDE ( __ascii_wctomb = 0x40058ef0 );
|
||||
PROVIDE ( asctime = 0x40059588 );
|
||||
PROVIDE ( asctime_r = 0x40000ec8 );
|
||||
PROVIDE ( __ashldi3 = 0x4000c818 );
|
||||
PROVIDE ( __ashrdi3 = 0x4000c830 );
|
||||
PROVIDE ( atoi = 0x400566c4 );
|
||||
PROVIDE ( _atoi_r = 0x400566d4 );
|
||||
PROVIDE ( atol = 0x400566ec );
|
||||
PROVIDE ( _atol_r = 0x400566fc );
|
||||
PROVIDE ( base64_decode = 0x4005ced8 );
|
||||
PROVIDE ( base64_encode = 0x4005cdbc );
|
||||
PROVIDE ( BasePoint_x_256 = 0x3ff97488 );
|
||||
@ -49,7 +41,6 @@ PROVIDE ( btdm_r_modules_func_p_get = 0x4005427c );
|
||||
PROVIDE ( btdm_r_modules_func_p_set = 0x40054270 );
|
||||
PROVIDE ( btdm_r_plf_func_p_set = 0x40054288 );
|
||||
PROVIDE ( bt_util_buf_env = 0x3ffb8bd4 );
|
||||
PROVIDE ( bzero = 0x4000c1f4 );
|
||||
PROVIDE ( cache_flash_mmu_set_rom = 0x400095e0 );
|
||||
PROVIDE ( Cache_Flush_rom = 0x40009a14 );
|
||||
PROVIDE ( Cache_Read_Disable_rom = 0x40009ab8 );
|
||||
@ -60,10 +51,7 @@ PROVIDE ( cache_sram_mmu_set_rom = 0x400097f4 );
|
||||
PROVIDE ( calc_rtc_memory_crc = 0x40008170 );
|
||||
PROVIDE ( calloc = 0x4000bee4 );
|
||||
PROVIDE ( _calloc_r = 0x4000bbf8 );
|
||||
PROVIDE ( _cleanup = 0x40001df8 );
|
||||
PROVIDE ( _cleanup_r = 0x40001d48 );
|
||||
PROVIDE ( __clear_cache = 0x40063860 );
|
||||
PROVIDE ( close = 0x40001778 );
|
||||
PROVIDE ( _close_r = 0x4000bd3c );
|
||||
PROVIDE ( __clrsbdi2 = 0x40064a38 );
|
||||
PROVIDE ( __clrsbsi2 = 0x40064a20 );
|
||||
@ -79,9 +67,6 @@ PROVIDE ( crc32_be = 0x4005d024 );
|
||||
PROVIDE ( crc32_le = 0x4005cfec );
|
||||
PROVIDE ( crc8_be = 0x4005d114 );
|
||||
PROVIDE ( crc8_le = 0x4005d0e0 );
|
||||
PROVIDE ( creat = 0x40000e8c );
|
||||
PROVIDE ( ctime = 0x400595b0 );
|
||||
PROVIDE ( ctime_r = 0x400595c4 );
|
||||
PROVIDE ( _ctype_ = 0x3ff96354 );
|
||||
PROVIDE ( __ctype_ptr__ = 0x3ff96350 );
|
||||
PROVIDE ( __ctzdi2 = 0x4000ca64 );
|
||||
@ -118,7 +103,6 @@ PROVIDE ( dh_group2_generator = 0x3ff9ada2 );
|
||||
PROVIDE ( dh_group2_prime = 0x3ff9ad22 );
|
||||
PROVIDE ( dh_group5_generator = 0x3ff9ad21 );
|
||||
PROVIDE ( dh_group5_prime = 0x3ff9ac61 );
|
||||
PROVIDE ( div = 0x40056348 );
|
||||
PROVIDE ( __divdc3 = 0x40064460 );
|
||||
PROVIDE ( __divdf3 = 0x40002954 );
|
||||
PROVIDE ( __divdi3 = 0x4000ca84 );
|
||||
@ -126,14 +110,10 @@ PROVIDE ( __divsc3 = 0x40064200 );
|
||||
PROVIDE ( __divsf3 = 0x4000234c );
|
||||
PROVIDE ( __divsi3 = 0x4000c7b8 );
|
||||
PROVIDE ( g_rom_spiflash_dummy_len_plus = 0x3ffae290 );
|
||||
PROVIDE ( __dummy_lock = 0x4000c728 );
|
||||
PROVIDE ( __dummy_lock_try = 0x4000c730 );
|
||||
PROVIDE ( ecc_env = 0x3ffb8d60 );
|
||||
PROVIDE ( ecc_Jacobian_InfinityPoint256 = 0x3ff972e8 );
|
||||
PROVIDE ( em_buf_env = 0x3ffb8d74 );
|
||||
PROVIDE ( environ = 0x3ffae0b4 );
|
||||
PROVIDE ( __env_lock = 0x40001fd4 );
|
||||
PROVIDE ( __env_unlock = 0x40001fe0 );
|
||||
PROVIDE ( __eqdf2 = 0x400636a8 );
|
||||
PROVIDE ( __eqsf2 = 0x40063374 );
|
||||
PROVIDE ( esp_crc8 = 0x4005d144 );
|
||||
@ -143,13 +123,8 @@ PROVIDE ( ets_startup_callback = 0x3ffe0404 );
|
||||
PROVIDE ( exc_cause_table = 0x3ff991d0 );
|
||||
PROVIDE ( _exit_r = 0x4000bd28 );
|
||||
PROVIDE ( __extendsfdf2 = 0x40002c34 );
|
||||
PROVIDE ( fclose = 0x400020ac );
|
||||
PROVIDE ( _fclose_r = 0x40001fec );
|
||||
PROVIDE ( fflush = 0x40059394 );
|
||||
PROVIDE ( _fflush_r = 0x40059320 );
|
||||
PROVIDE ( __ffsdi2 = 0x4000ca2c );
|
||||
PROVIDE ( __ffssi2 = 0x4000c804 );
|
||||
PROVIDE ( _findenv_r = 0x40001f44 );
|
||||
PROVIDE ( __fixdfdi = 0x40002ac4 );
|
||||
PROVIDE ( __fixdfsi = 0x40002a78 );
|
||||
PROVIDE ( __fixsfdi = 0x4000244c );
|
||||
@ -165,31 +140,19 @@ PROVIDE ( __floatundidf = 0x4000c978 );
|
||||
PROVIDE ( __floatundisf = 0x4000c8b0 );
|
||||
PROVIDE ( __floatunsidf = 0x4000c938 );
|
||||
PROVIDE ( __floatunsisf = 0x4000c864 );
|
||||
PROVIDE ( __fp_lock_all = 0x40001f1c );
|
||||
PROVIDE ( __fp_unlock_all = 0x40001f30 );
|
||||
PROVIDE ( fputwc = 0x40058ea8 );
|
||||
PROVIDE ( __fputwc = 0x40058da0 );
|
||||
PROVIDE ( _fputwc_r = 0x40058e4c );
|
||||
PROVIDE ( free = 0x4000beb8 );
|
||||
PROVIDE ( _free_r = 0x4000bbcc );
|
||||
PROVIDE ( _fstat_r = 0x4000bccc );
|
||||
PROVIDE ( _fwalk = 0x4000c738 );
|
||||
PROVIDE ( _fwalk_reent = 0x4000c770 );
|
||||
PROVIDE ( __gcc_bcmp = 0x40064a70 );
|
||||
PROVIDE ( __gedf2 = 0x40063768 );
|
||||
PROVIDE ( __gesf2 = 0x4006340c );
|
||||
PROVIDE ( __get_current_time_locale = 0x40001834 );
|
||||
PROVIDE ( _getenv_r = 0x40001fbc );
|
||||
PROVIDE ( _getpid_r = 0x4000bcfc );
|
||||
PROVIDE ( __getreent = 0x4000be8c );
|
||||
PROVIDE ( _gettimeofday_r = 0x4000bc58 );
|
||||
PROVIDE ( __gettzinfo = 0x40001fcc );
|
||||
PROVIDE ( GF_Jacobian_Point_Addition256 = 0x400163a4 );
|
||||
PROVIDE ( GF_Jacobian_Point_Double256 = 0x40016260 );
|
||||
PROVIDE ( GF_Point_Jacobian_To_Affine256 = 0x40016b0c );
|
||||
PROVIDE ( _global_impure_ptr = 0x3ffae0b0 );
|
||||
PROVIDE ( gmtime = 0x40059848 );
|
||||
PROVIDE ( gmtime_r = 0x40059868 );
|
||||
PROVIDE ( g_phyFuns_instance = 0x3ffae0c4 );
|
||||
PROVIDE ( g_rom_flashchip = 0x3ffae270 );
|
||||
PROVIDE ( __gtdf2 = 0x400636dc );
|
||||
@ -216,26 +179,10 @@ PROVIDE ( hmac_sha1 = 0x40060acc );
|
||||
PROVIDE ( hmac_sha1_vector = 0x400609e4 );
|
||||
PROVIDE ( hmac_sha256 = 0x40060d58 );
|
||||
PROVIDE ( hmac_sha256_vector = 0x40060c84 );
|
||||
PROVIDE ( isalnum = 0x40000f04 );
|
||||
PROVIDE ( isalpha = 0x40000f18 );
|
||||
PROVIDE ( isascii = 0x4000c20c );
|
||||
PROVIDE ( _isatty_r = 0x40000ea0 );
|
||||
PROVIDE ( isblank = 0x40000f2c );
|
||||
PROVIDE ( iscntrl = 0x40000f50 );
|
||||
PROVIDE ( isdigit = 0x40000f64 );
|
||||
PROVIDE ( isgraph = 0x40000f94 );
|
||||
PROVIDE ( islower = 0x40000f78 );
|
||||
PROVIDE ( isprint = 0x40000fa8 );
|
||||
PROVIDE ( ispunct = 0x40000fc0 );
|
||||
PROVIDE ( isspace = 0x40000fd4 );
|
||||
PROVIDE ( isupper = 0x40000fe8 );
|
||||
PROVIDE ( itoa = 0x400566b4 );
|
||||
PROVIDE ( __itoa = 0x40056678 );
|
||||
PROVIDE ( jd_decomp = 0x400613e8 );
|
||||
PROVIDE ( jd_prepare = 0x40060fa8 );
|
||||
PROVIDE ( ke_env = 0x3ffb93cc );
|
||||
PROVIDE ( _kill_r = 0x4000bd10 );
|
||||
PROVIDE ( labs = 0x40056370 );
|
||||
PROVIDE ( lb_default_handler = 0x3ff982b8 );
|
||||
PROVIDE ( lb_default_state_tab_p_get = 0x4001c198 );
|
||||
PROVIDE ( lb_env = 0x3ffb9424 );
|
||||
@ -251,7 +198,6 @@ PROVIDE ( ld_acl_br_types = 0x3ff98a36 );
|
||||
PROVIDE ( ld_acl_edr_sizes = 0x3ff98a14 );
|
||||
PROVIDE ( ld_acl_edr_types = 0x3ff98a22 );
|
||||
PROVIDE ( ld_env = 0x3ffb9510 );
|
||||
PROVIDE ( ldiv = 0x40056378 );
|
||||
PROVIDE ( ld_pcm_settings_dft = 0x3ff98a0c );
|
||||
PROVIDE ( ld_sched_params = 0x3ffb96c0 );
|
||||
PROVIDE ( ld_sync_train_channels = 0x3ff98a3c );
|
||||
@ -292,25 +238,14 @@ PROVIDE ( lm_n_page_tab = 0x3ff990e8 );
|
||||
PROVIDE ( lmp_desc_tab = 0x3ff96e6c );
|
||||
PROVIDE ( lmp_ext_desc_tab = 0x3ff96d9c );
|
||||
PROVIDE ( lm_state = 0x3ffb9a1c );
|
||||
PROVIDE ( __locale_charset = 0x40059540 );
|
||||
PROVIDE ( __locale_cjk_lang = 0x40059558 );
|
||||
PROVIDE ( localeconv = 0x4005957c );
|
||||
PROVIDE ( _localeconv_r = 0x40059560 );
|
||||
PROVIDE ( __locale_mb_cur_max = 0x40059548 );
|
||||
PROVIDE ( __locale_msgcharset = 0x40059550 );
|
||||
PROVIDE ( localtime = 0x400595dc );
|
||||
PROVIDE ( localtime_r = 0x400595fc );
|
||||
PROVIDE ( _lock_acquire = 0x4000be14 );
|
||||
PROVIDE ( _lock_acquire_recursive = 0x4000be28 );
|
||||
PROVIDE ( _lock_close = 0x4000bdec );
|
||||
PROVIDE ( _lock_close_recursive = 0x4000be00 );
|
||||
PROVIDE ( _lock_init = 0x4000bdc4 );
|
||||
PROVIDE ( _lock_init_recursive = 0x4000bdd8 );
|
||||
PROVIDE ( _lock_release = 0x4000be64 );
|
||||
PROVIDE ( _lock_release_recursive = 0x4000be78 );
|
||||
PROVIDE ( _lock_try_acquire = 0x4000be3c );
|
||||
PROVIDE ( _lock_try_acquire_recursive = 0x4000be50 );
|
||||
PROVIDE ( longjmp = 0x400562cc );
|
||||
PROVIDE ( _lseek_r = 0x4000bd8c );
|
||||
PROVIDE ( __lshrdi3 = 0x4000c84c );
|
||||
PROVIDE ( __ltdf2 = 0x40063790 );
|
||||
@ -323,14 +258,6 @@ PROVIDE ( MD5Final = 0x4005db1c );
|
||||
PROVIDE ( MD5Init = 0x4005da7c );
|
||||
PROVIDE ( MD5Update = 0x4005da9c );
|
||||
PROVIDE ( md5_vector = 0x4005db80 );
|
||||
PROVIDE ( memccpy = 0x4000c220 );
|
||||
PROVIDE ( memchr = 0x4000c244 );
|
||||
PROVIDE ( memcmp = 0x4000c260 );
|
||||
PROVIDE ( memcpy = 0x4000c2c8 );
|
||||
PROVIDE ( memmove = 0x4000c3c0 );
|
||||
PROVIDE ( memrchr = 0x4000c400 );
|
||||
PROVIDE ( memset = 0x4000c44c );
|
||||
PROVIDE ( mktime = 0x4005a5e8 );
|
||||
PROVIDE ( mmu_init = 0x400095a4 );
|
||||
PROVIDE ( __moddi3 = 0x4000cd4c );
|
||||
PROVIDE ( __modsi3 = 0x4000c7c0 );
|
||||
@ -360,7 +287,6 @@ PROVIDE ( __nesf2 = 0x40063374 );
|
||||
PROVIDE ( notEqual256 = 0x40015b04 );
|
||||
PROVIDE ( __nsau_data = 0x3ff96544 );
|
||||
PROVIDE ( one_bits = 0x3ff971f8 );
|
||||
PROVIDE ( open = 0x4000178c );
|
||||
PROVIDE ( _open_r = 0x4000bd54 );
|
||||
PROVIDE ( __paritysi2 = 0x40002f3c );
|
||||
PROVIDE ( pbkdf2_sha1 = 0x40060ba4 );
|
||||
@ -372,10 +298,6 @@ PROVIDE ( __powidf2 = 0x400638d4 );
|
||||
PROVIDE ( __powisf2 = 0x4006389c );
|
||||
PROVIDE ( _Pri_4_HandlerAddress = 0x3ffe0648 );
|
||||
PROVIDE ( _Pri_5_HandlerAddress = 0x3ffe064c );
|
||||
PROVIDE ( qsort = 0x40056424 );
|
||||
PROVIDE ( _raise_r = 0x4000bc70 );
|
||||
PROVIDE ( rand = 0x40001058 );
|
||||
PROVIDE ( rand_r = 0x400010d4 );
|
||||
PROVIDE ( r_btdm_option_data = 0x3ffae6e0 );
|
||||
PROVIDE ( r_bt_util_buf_acl_rx_alloc = 0x40010218 );
|
||||
PROVIDE ( r_bt_util_buf_acl_rx_free = 0x40010234 );
|
||||
@ -419,7 +341,6 @@ PROVIDE ( r_E22 = 0x400109b4 );
|
||||
PROVIDE ( r_E3 = 0x40010a58 );
|
||||
PROVIDE ( r_ea_alarm_clear = 0x40015ab4 );
|
||||
PROVIDE ( r_ea_alarm_set = 0x40015a10 );
|
||||
PROVIDE ( read = 0x400017dc );
|
||||
PROVIDE ( _read_r = 0x4000bda8 );
|
||||
PROVIDE ( r_ea_elt_cancel = 0x400150d0 );
|
||||
PROVIDE ( r_ea_elt_create = 0x40015264 );
|
||||
@ -1440,24 +1361,10 @@ PROVIDE ( rwip_priority = 0x3ff99159 );
|
||||
PROVIDE ( rwip_rf = 0x3ffbdb28 );
|
||||
PROVIDE ( rwip_rf_p_get = 0x400558f4 );
|
||||
PROVIDE ( r_XorKey = 0x400112c0 );
|
||||
PROVIDE ( sbrk = 0x400017f4 );
|
||||
PROVIDE ( _sbrk_r = 0x4000bce4 );
|
||||
PROVIDE ( __sccl = 0x4000c498 );
|
||||
PROVIDE ( __sclose = 0x400011b8 );
|
||||
PROVIDE ( __seofread = 0x40001148 );
|
||||
PROVIDE ( setjmp = 0x40056268 );
|
||||
PROVIDE ( setlocale = 0x40059568 );
|
||||
PROVIDE ( _setlocale_r = 0x4005950c );
|
||||
PROVIDE ( __sf_fake_stderr = 0x3ff96458 );
|
||||
PROVIDE ( __sf_fake_stdin = 0x3ff96498 );
|
||||
PROVIDE ( __sf_fake_stdout = 0x3ff96478 );
|
||||
PROVIDE ( __sflush_r = 0x400591e0 );
|
||||
PROVIDE ( __sfmoreglue = 0x40001dc8 );
|
||||
PROVIDE ( __sfp = 0x40001e90 );
|
||||
PROVIDE ( __sfp_lock_acquire = 0x40001e08 );
|
||||
PROVIDE ( __sfp_lock_release = 0x40001e14 );
|
||||
PROVIDE ( __sfputs_r = 0x40057790 );
|
||||
PROVIDE ( __sfvwrite_r = 0x4005893c );
|
||||
PROVIDE ( sha1_prf = 0x40060ae8 );
|
||||
PROVIDE ( sha1_vector = 0x40060b64 );
|
||||
PROVIDE ( sha256_prf = 0x40060d70 );
|
||||
@ -1466,9 +1373,6 @@ PROVIDE ( sha_blk_bits = 0x3ff99290 );
|
||||
PROVIDE ( sha_blk_bits_bytes = 0x3ff99288 );
|
||||
PROVIDE ( sha_blk_hash_bytes = 0x3ff9928c );
|
||||
PROVIDE ( sig_matrix = 0x3ffae293 );
|
||||
PROVIDE ( __sinit = 0x40001e38 );
|
||||
PROVIDE ( __sinit_lock_acquire = 0x40001e20 );
|
||||
PROVIDE ( __sinit_lock_release = 0x40001e2c );
|
||||
PROVIDE ( sip_after_tx_complete = 0x4000b358 );
|
||||
PROVIDE ( sip_alloc_to_host_evt = 0x4000ab9c );
|
||||
PROVIDE ( sip_get_ptr = 0x4000b34c );
|
||||
@ -1494,15 +1398,7 @@ PROVIDE ( slc_reattach = 0x4000b62c );
|
||||
PROVIDE ( slc_send_to_host_chain = 0x4000b6a0 );
|
||||
PROVIDE ( slc_set_host_io_max_window = 0x4000b89c );
|
||||
PROVIDE ( slc_to_host_chain_recycle = 0x4000b758 );
|
||||
PROVIDE ( __smakebuf_r = 0x40059108 );
|
||||
PROVIDE ( specialModP256 = 0x4001600c );
|
||||
PROVIDE ( srand = 0x40001004 );
|
||||
PROVIDE ( __sread = 0x40001118 );
|
||||
PROVIDE ( __srefill_r = 0x400593d4 );
|
||||
PROVIDE ( __sseek = 0x40001184 );
|
||||
PROVIDE ( __ssprint_r = 0x40056ff8 );
|
||||
PROVIDE ( __ssputs_r = 0x40056f2c );
|
||||
PROVIDE ( __ssrefill_r = 0x40057fec );
|
||||
PROVIDE ( __stack = 0x3ffe3f20 );
|
||||
PROVIDE ( __stack_app = 0x3ffe7e30 );
|
||||
PROVIDE ( _stack_sentry = 0x3ffe1320 );
|
||||
@ -1511,41 +1407,7 @@ PROVIDE ( _start = 0x40000704 );
|
||||
PROVIDE ( start_tb_console = 0x4005a980 );
|
||||
PROVIDE ( _stat_r = 0x4000bcb4 );
|
||||
PROVIDE ( _stext = 0x40000560 );
|
||||
PROVIDE ( strcasecmp = 0x400011cc );
|
||||
PROVIDE ( strcasestr = 0x40001210 );
|
||||
PROVIDE ( strcat = 0x4000c518 );
|
||||
PROVIDE ( strchr = 0x4000c53c );
|
||||
PROVIDE ( strcmp = 0x40001274 );
|
||||
PROVIDE ( strcoll = 0x40001398 );
|
||||
PROVIDE ( strcpy = 0x400013ac );
|
||||
PROVIDE ( strcspn = 0x4000c558 );
|
||||
PROVIDE ( strdup = 0x4000143c );
|
||||
PROVIDE ( _strdup_r = 0x40001450 );
|
||||
PROVIDE ( strftime = 0x40059ab4 );
|
||||
PROVIDE ( strlcat = 0x40001470 );
|
||||
PROVIDE ( strlcpy = 0x4000c584 );
|
||||
PROVIDE ( strlen = 0x400014c0 );
|
||||
PROVIDE ( strlwr = 0x40001524 );
|
||||
PROVIDE ( strncasecmp = 0x40001550 );
|
||||
PROVIDE ( strncat = 0x4000c5c4 );
|
||||
PROVIDE ( strncmp = 0x4000c5f4 );
|
||||
PROVIDE ( strncpy = 0x400015d4 );
|
||||
PROVIDE ( strndup = 0x400016b0 );
|
||||
PROVIDE ( _strndup_r = 0x400016c4 );
|
||||
PROVIDE ( strnlen = 0x4000c628 );
|
||||
PROVIDE ( strrchr = 0x40001708 );
|
||||
PROVIDE ( strsep = 0x40001734 );
|
||||
PROVIDE ( strspn = 0x4000c648 );
|
||||
PROVIDE ( strstr = 0x4000c674 );
|
||||
PROVIDE ( __strtok_r = 0x4000c6a8 );
|
||||
PROVIDE ( strtok_r = 0x4000c70c );
|
||||
PROVIDE ( strtol = 0x4005681c );
|
||||
PROVIDE ( _strtol_r = 0x40056714 );
|
||||
PROVIDE ( strtoul = 0x4005692c );
|
||||
PROVIDE ( _strtoul_r = 0x40056834 );
|
||||
PROVIDE ( strupr = 0x4000174c );
|
||||
PROVIDE ( __subdf3 = 0x400026e4 );
|
||||
PROVIDE ( __submore = 0x40058f3c );
|
||||
PROVIDE ( __subsf3 = 0x400021d0 );
|
||||
PROVIDE ( SubtractBigHex256 = 0x40015bcc );
|
||||
PROVIDE ( SubtractBigHexMod256 = 0x40015e8c );
|
||||
@ -1554,15 +1416,9 @@ PROVIDE ( SubtractFromSelfBigHex256 = 0x40015c20 );
|
||||
PROVIDE ( SubtractFromSelfBigHexSign256 = 0x40015dc8 );
|
||||
PROVIDE ( __subvdi3 = 0x40002d20 );
|
||||
PROVIDE ( __subvsi3 = 0x40002cf8 );
|
||||
PROVIDE ( _sungetc_r = 0x40057f6c );
|
||||
PROVIDE ( __swbuf = 0x40058cb4 );
|
||||
PROVIDE ( __swbuf_r = 0x40058bec );
|
||||
PROVIDE ( __swrite = 0x40001150 );
|
||||
PROVIDE ( __swsetup_r = 0x40058cc8 );
|
||||
PROVIDE ( sw_to_hw = 0x3ffb8d40 );
|
||||
PROVIDE ( syscall_table_ptr_app = 0x3ffae020 );
|
||||
PROVIDE ( syscall_table_ptr_pro = 0x3ffae024 );
|
||||
PROVIDE ( _system_r = 0x4000bc10 );
|
||||
PROVIDE ( tdefl_compress = 0x400600bc );
|
||||
PROVIDE ( tdefl_compress_buffer = 0x400607f4 );
|
||||
PROVIDE ( tdefl_compress_mem_to_mem = 0x40060900 );
|
||||
@ -1572,24 +1428,13 @@ PROVIDE ( tdefl_get_prev_return_status = 0x400608d0 );
|
||||
PROVIDE ( tdefl_init = 0x40060810 );
|
||||
PROVIDE ( tdefl_write_image_to_png_file_in_memory = 0x4006091c );
|
||||
PROVIDE ( tdefl_write_image_to_png_file_in_memory_ex = 0x40060910 );
|
||||
PROVIDE ( time = 0x40001844 );
|
||||
PROVIDE ( __time_load_locale = 0x4000183c );
|
||||
PROVIDE ( times = 0x40001808 );
|
||||
PROVIDE ( _times_r = 0x4000bc40 );
|
||||
PROVIDE ( _timezone = 0x3ffae0a0 );
|
||||
PROVIDE ( tinfl_decompress = 0x4005ef30 );
|
||||
PROVIDE ( tinfl_decompress_mem_to_callback = 0x40060090 );
|
||||
PROVIDE ( tinfl_decompress_mem_to_mem = 0x40060050 );
|
||||
PROVIDE ( toascii = 0x4000c720 );
|
||||
PROVIDE ( tolower = 0x40001868 );
|
||||
PROVIDE ( toupper = 0x40001884 );
|
||||
PROVIDE ( __truncdfsf2 = 0x40002b90 );
|
||||
PROVIDE ( __tzcalc_limits = 0x400018a0 );
|
||||
PROVIDE ( __tz_lock = 0x40001a04 );
|
||||
PROVIDE ( _tzname = 0x3ffae030 );
|
||||
PROVIDE ( tzset = 0x40001a1c );
|
||||
PROVIDE ( _tzset_r = 0x40001a28 );
|
||||
PROVIDE ( __tz_unlock = 0x40001a10 );
|
||||
PROVIDE ( UartDev = 0x3ffe019c );
|
||||
PROVIDE ( __ucmpdi2 = 0x40063840 );
|
||||
PROVIDE ( __udivdi3 = 0x4000cff8 );
|
||||
@ -1599,20 +1444,12 @@ PROVIDE ( __udiv_w_sdiv = 0x40064aa8 );
|
||||
PROVIDE ( __umoddi3 = 0x4000d280 );
|
||||
PROVIDE ( __umodsi3 = 0x4000c7d0 );
|
||||
PROVIDE ( __umulsidi3 = 0x4000c7d8 );
|
||||
PROVIDE ( ungetc = 0x400590f4 );
|
||||
PROVIDE ( _ungetc_r = 0x40058fa0 );
|
||||
PROVIDE ( _unlink_r = 0x4000bc84 );
|
||||
PROVIDE ( __unorddf2 = 0x400637f4 );
|
||||
PROVIDE ( __unordsf2 = 0x40063478 );
|
||||
PROVIDE ( user_code_start = 0x3ffe0400 );
|
||||
PROVIDE ( utoa = 0x40056258 );
|
||||
PROVIDE ( __utoa = 0x400561f0 );
|
||||
PROVIDE ( veryBigHexP256 = 0x3ff9736c );
|
||||
PROVIDE ( wcrtomb = 0x40058920 );
|
||||
PROVIDE ( _wcrtomb_r = 0x400588d8 );
|
||||
PROVIDE ( __wctomb = 0x3ff96540 );
|
||||
PROVIDE ( _wctomb_r = 0x40058f14 );
|
||||
PROVIDE ( write = 0x4000181c );
|
||||
PROVIDE ( _write_r = 0x4000bd70 );
|
||||
PROVIDE ( xthal_bcopy = 0x4000c098 );
|
||||
PROVIDE ( xthal_copy123 = 0x4000c124 );
|
||||
|
167
components/esp32/ld/esp32.rom.spiram_incompatible_fns.ld
Normal file
167
components/esp32/ld/esp32.rom.spiram_incompatible_fns.ld
Normal file
@ -0,0 +1,167 @@
|
||||
/*
|
||||
If the spiram compiler workaround is active, these functions from ROM cannot be used. If the workaround is not
|
||||
active (e.g. because the system does not use SPI RAM) then these functions are okay to use.
|
||||
*/
|
||||
PROVIDE ( abs = 0x40056340 );
|
||||
PROVIDE ( __ascii_wctomb = 0x40058ef0 );
|
||||
PROVIDE ( asctime = 0x40059588 );
|
||||
PROVIDE ( asctime_r = 0x40000ec8 );
|
||||
PROVIDE ( atoi = 0x400566c4 );
|
||||
PROVIDE ( _atoi_r = 0x400566d4 );
|
||||
PROVIDE ( atol = 0x400566ec );
|
||||
PROVIDE ( _atol_r = 0x400566fc );
|
||||
PROVIDE ( bzero = 0x4000c1f4 );
|
||||
PROVIDE ( _cleanup = 0x40001df8 );
|
||||
PROVIDE ( _cleanup_r = 0x40001d48 );
|
||||
PROVIDE ( close = 0x40001778 );
|
||||
PROVIDE ( creat = 0x40000e8c );
|
||||
PROVIDE ( ctime = 0x400595b0 );
|
||||
PROVIDE ( ctime_r = 0x400595c4 );
|
||||
PROVIDE ( div = 0x40056348 );
|
||||
PROVIDE ( __dummy_lock = 0x4000c728 );
|
||||
PROVIDE ( __dummy_lock_try = 0x4000c730 );
|
||||
PROVIDE ( __env_lock = 0x40001fd4 );
|
||||
PROVIDE ( __env_unlock = 0x40001fe0 );
|
||||
PROVIDE ( fclose = 0x400020ac );
|
||||
PROVIDE ( _fclose_r = 0x40001fec );
|
||||
PROVIDE ( fflush = 0x40059394 );
|
||||
PROVIDE ( _fflush_r = 0x40059320 );
|
||||
PROVIDE ( _findenv_r = 0x40001f44 );
|
||||
PROVIDE ( __fp_lock_all = 0x40001f1c );
|
||||
PROVIDE ( __fp_unlock_all = 0x40001f30 );
|
||||
PROVIDE ( fputwc = 0x40058ea8 );
|
||||
PROVIDE ( __fputwc = 0x40058da0 );
|
||||
PROVIDE ( _fputwc_r = 0x40058e4c );
|
||||
PROVIDE ( _fwalk = 0x4000c738 );
|
||||
PROVIDE ( _fwalk_reent = 0x4000c770 );
|
||||
PROVIDE ( __get_current_time_locale = 0x40001834 );
|
||||
PROVIDE ( _getenv_r = 0x40001fbc );
|
||||
PROVIDE ( __gettzinfo = 0x40001fcc );
|
||||
PROVIDE ( gmtime = 0x40059848 );
|
||||
PROVIDE ( gmtime_r = 0x40059868 );
|
||||
PROVIDE ( isalnum = 0x40000f04 );
|
||||
PROVIDE ( isalpha = 0x40000f18 );
|
||||
PROVIDE ( isascii = 0x4000c20c );
|
||||
PROVIDE ( _isatty_r = 0x40000ea0 );
|
||||
PROVIDE ( isblank = 0x40000f2c );
|
||||
PROVIDE ( iscntrl = 0x40000f50 );
|
||||
PROVIDE ( isdigit = 0x40000f64 );
|
||||
PROVIDE ( isgraph = 0x40000f94 );
|
||||
PROVIDE ( islower = 0x40000f78 );
|
||||
PROVIDE ( isprint = 0x40000fa8 );
|
||||
PROVIDE ( ispunct = 0x40000fc0 );
|
||||
PROVIDE ( isspace = 0x40000fd4 );
|
||||
PROVIDE ( isupper = 0x40000fe8 );
|
||||
PROVIDE ( itoa = 0x400566b4 );
|
||||
PROVIDE ( __itoa = 0x40056678 );
|
||||
PROVIDE ( labs = 0x40056370 );
|
||||
PROVIDE ( ldiv = 0x40056378 );
|
||||
PROVIDE ( __locale_charset = 0x40059540 );
|
||||
PROVIDE ( __locale_cjk_lang = 0x40059558 );
|
||||
PROVIDE ( localeconv = 0x4005957c );
|
||||
PROVIDE ( _localeconv_r = 0x40059560 );
|
||||
PROVIDE ( __locale_mb_cur_max = 0x40059548 );
|
||||
PROVIDE ( __locale_msgcharset = 0x40059550 );
|
||||
PROVIDE ( localtime = 0x400595dc );
|
||||
PROVIDE ( localtime_r = 0x400595fc );
|
||||
PROVIDE ( _lock_acquire = 0x4000be14 );
|
||||
PROVIDE ( _lock_release = 0x4000be64 );
|
||||
PROVIDE ( longjmp = 0x400562cc );
|
||||
PROVIDE ( memccpy = 0x4000c220 );
|
||||
PROVIDE ( memchr = 0x4000c244 );
|
||||
PROVIDE ( memcmp = 0x4000c260 );
|
||||
PROVIDE ( memcpy = 0x4000c2c8 );
|
||||
PROVIDE ( memmove = 0x4000c3c0 );
|
||||
PROVIDE ( memrchr = 0x4000c400 );
|
||||
PROVIDE ( memset = 0x4000c44c );
|
||||
PROVIDE ( mktime = 0x4005a5e8 );
|
||||
PROVIDE ( open = 0x4000178c );
|
||||
PROVIDE ( qsort = 0x40056424 );
|
||||
PROVIDE ( _raise_r = 0x4000bc70 );
|
||||
PROVIDE ( rand = 0x40001058 );
|
||||
PROVIDE ( rand_r = 0x400010d4 );
|
||||
PROVIDE ( read = 0x400017dc );
|
||||
PROVIDE ( sbrk = 0x400017f4 );
|
||||
PROVIDE ( __sccl = 0x4000c498 );
|
||||
PROVIDE ( __sclose = 0x400011b8 );
|
||||
PROVIDE ( __seofread = 0x40001148 );
|
||||
PROVIDE ( setjmp = 0x40056268 );
|
||||
PROVIDE ( setlocale = 0x40059568 );
|
||||
PROVIDE ( _setlocale_r = 0x4005950c );
|
||||
PROVIDE ( __sflush_r = 0x400591e0 );
|
||||
PROVIDE ( __sfmoreglue = 0x40001dc8 );
|
||||
PROVIDE ( __sfp = 0x40001e90 );
|
||||
PROVIDE ( __sfp_lock_acquire = 0x40001e08 );
|
||||
PROVIDE ( __sfp_lock_release = 0x40001e14 );
|
||||
PROVIDE ( __sfputs_r = 0x40057790 );
|
||||
PROVIDE ( __sfvwrite_r = 0x4005893c );
|
||||
PROVIDE ( __sinit = 0x40001e38 );
|
||||
PROVIDE ( __sinit_lock_acquire = 0x40001e20 );
|
||||
PROVIDE ( __sinit_lock_release = 0x40001e2c );
|
||||
PROVIDE ( __smakebuf_r = 0x40059108 );
|
||||
PROVIDE ( srand = 0x40001004 );
|
||||
PROVIDE ( __sread = 0x40001118 );
|
||||
PROVIDE ( __srefill_r = 0x400593d4 );
|
||||
PROVIDE ( __sseek = 0x40001184 );
|
||||
PROVIDE ( __ssprint_r = 0x40056ff8 );
|
||||
PROVIDE ( __ssputs_r = 0x40056f2c );
|
||||
PROVIDE ( __ssrefill_r = 0x40057fec );
|
||||
PROVIDE ( strcasecmp = 0x400011cc );
|
||||
PROVIDE ( strcasestr = 0x40001210 );
|
||||
PROVIDE ( strcat = 0x4000c518 );
|
||||
PROVIDE ( strchr = 0x4000c53c );
|
||||
PROVIDE ( strcmp = 0x40001274 );
|
||||
PROVIDE ( strcoll = 0x40001398 );
|
||||
PROVIDE ( strcpy = 0x400013ac );
|
||||
PROVIDE ( strcspn = 0x4000c558 );
|
||||
PROVIDE ( strdup = 0x4000143c );
|
||||
PROVIDE ( _strdup_r = 0x40001450 );
|
||||
PROVIDE ( strftime = 0x40059ab4 );
|
||||
PROVIDE ( strlcat = 0x40001470 );
|
||||
PROVIDE ( strlcpy = 0x4000c584 );
|
||||
PROVIDE ( strlen = 0x400014c0 );
|
||||
PROVIDE ( strlwr = 0x40001524 );
|
||||
PROVIDE ( strncasecmp = 0x40001550 );
|
||||
PROVIDE ( strncat = 0x4000c5c4 );
|
||||
PROVIDE ( strncmp = 0x4000c5f4 );
|
||||
PROVIDE ( strncpy = 0x400015d4 );
|
||||
PROVIDE ( strndup = 0x400016b0 );
|
||||
PROVIDE ( _strndup_r = 0x400016c4 );
|
||||
PROVIDE ( strnlen = 0x4000c628 );
|
||||
PROVIDE ( strrchr = 0x40001708 );
|
||||
PROVIDE ( strsep = 0x40001734 );
|
||||
PROVIDE ( strspn = 0x4000c648 );
|
||||
PROVIDE ( strstr = 0x4000c674 );
|
||||
PROVIDE ( __strtok_r = 0x4000c6a8 );
|
||||
PROVIDE ( strtok_r = 0x4000c70c );
|
||||
PROVIDE ( strtol = 0x4005681c );
|
||||
PROVIDE ( _strtol_r = 0x40056714 );
|
||||
PROVIDE ( strtoul = 0x4005692c );
|
||||
PROVIDE ( _strtoul_r = 0x40056834 );
|
||||
PROVIDE ( strupr = 0x4000174c );
|
||||
PROVIDE ( __submore = 0x40058f3c );
|
||||
PROVIDE ( _sungetc_r = 0x40057f6c );
|
||||
PROVIDE ( __swbuf = 0x40058cb4 );
|
||||
PROVIDE ( __swbuf_r = 0x40058bec );
|
||||
PROVIDE ( __swrite = 0x40001150 );
|
||||
PROVIDE ( __swsetup_r = 0x40058cc8 );
|
||||
PROVIDE ( _system_r = 0x4000bc10 );
|
||||
PROVIDE ( time = 0x40001844 );
|
||||
PROVIDE ( __time_load_locale = 0x4000183c );
|
||||
PROVIDE ( times = 0x40001808 );
|
||||
PROVIDE ( toascii = 0x4000c720 );
|
||||
PROVIDE ( tolower = 0x40001868 );
|
||||
PROVIDE ( toupper = 0x40001884 );
|
||||
PROVIDE ( __tzcalc_limits = 0x400018a0 );
|
||||
PROVIDE ( __tz_lock = 0x40001a04 );
|
||||
PROVIDE ( tzset = 0x40001a1c );
|
||||
PROVIDE ( _tzset_r = 0x40001a28 );
|
||||
PROVIDE ( __tz_unlock = 0x40001a10 );
|
||||
PROVIDE ( ungetc = 0x400590f4 );
|
||||
PROVIDE ( _ungetc_r = 0x40058fa0 );
|
||||
PROVIDE ( utoa = 0x40056258 );
|
||||
PROVIDE ( __utoa = 0x400561f0 );
|
||||
PROVIDE ( wcrtomb = 0x40058920 );
|
||||
PROVIDE ( _wcrtomb_r = 0x400588d8 );
|
||||
PROVIDE ( _wctomb_r = 0x40058f14 );
|
||||
PROVIDE ( write = 0x4000181c );
|
BIN
components/esp32/libstdcc++-cache-workaround.a
Normal file
BIN
components/esp32/libstdcc++-cache-workaround.a
Normal file
Binary file not shown.
184
components/esp32/spiram.c
Normal file
184
components/esp32/spiram.c
Normal file
@ -0,0 +1,184 @@
|
||||
/*
|
||||
Abstraction layer for spi-ram. For now, it's no more than a stub for the spiram_psram functions, but if
|
||||
we add more types of external RAM memory, this can be made into a more intelligent dispatcher.
|
||||
*/
|
||||
|
||||
// Copyright 2015-2017 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_attr.h"
|
||||
#include "esp_err.h"
|
||||
#include "spiram_psram.h"
|
||||
#include "esp_log.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/xtensa_api.h"
|
||||
#include "soc/soc.h"
|
||||
#include "soc/dport_reg.h"
|
||||
#include "rom/cache.h"
|
||||
|
||||
#if CONFIG_FREERTOS_UNICORE
|
||||
#define PSRAM_MODE PSRAM_VADDR_MODE_NORMAL
|
||||
#else
|
||||
#if CONFIG_MEMMAP_SPIRAM_CACHE_EVENODD
|
||||
#define PSRAM_MODE PSRAM_VADDR_MODE_EVENODD
|
||||
#else
|
||||
#define PSRAM_MODE PSRAM_VADDR_MODE_LOWHIGH
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if CONFIG_SPIRAM_SUPPORT
|
||||
|
||||
static const char* TAG = "spiram";
|
||||
|
||||
#if CONFIG_SPIRAM_SPEED_40M && CONFIG_ESPTOOLPY_FLASHFREQ_40M
|
||||
#define PSRAM_SPEED PSRAM_CACHE_F40M_S40M
|
||||
#elif CONFIG_SPIRAM_SPEED_40M && CONFIG_ESPTOOLPY_FLASHFREQ_80M
|
||||
#define PSRAM_SPEED PSRAM_CACHE_F80M_S40M
|
||||
#elif CONFIG_SPIRAM_SPEED_80M && CONFIG_ESPTOOLPY_FLASHFREQ_80M
|
||||
#define PSRAM_SPEED PSRAM_CACHE_F80M_S80M
|
||||
#else
|
||||
#error "FLASH speed can only be equal to or higher than SRAM speed while SRAM is enabled!"
|
||||
#endif
|
||||
|
||||
|
||||
static bool spiram_inited=false;
|
||||
|
||||
|
||||
/*
|
||||
Simple RAM test. Writes a word every 32 bytes. Takes about a second to complete for 4MiB. Returns
|
||||
true when RAM seems OK, false when test fails. WARNING: Do not run this before the 2nd cpu has been
|
||||
initialized (in a two-core system) or after the heap allocator has taken ownership of the memory.
|
||||
*/
|
||||
bool esp_spiram_test()
|
||||
{
|
||||
volatile int *spiram=(volatile int*)SOC_EXTRAM_DATA_LOW;
|
||||
size_t p;
|
||||
size_t s=CONFIG_SPIRAM_SIZE;
|
||||
int errct=0;
|
||||
int initial_err=-1;
|
||||
for (p=0; p<(s/sizeof(int)); p+=8) {
|
||||
spiram[p]=p^0xAAAAAAAA;
|
||||
}
|
||||
for (p=0; p<(s/sizeof(int)); p+=8) {
|
||||
if (spiram[p]!=(p^0xAAAAAAAA)) {
|
||||
errct++;
|
||||
if (errct==1) initial_err=p*4;
|
||||
}
|
||||
}
|
||||
if (errct) {
|
||||
ESP_EARLY_LOGE(TAG, "SPI SRAM memory test fail. %d/%d writes failed, first @ %X\n", errct, s/32, initial_err+SOC_EXTRAM_DATA_LOW);
|
||||
return false;
|
||||
} else {
|
||||
ESP_EARLY_LOGI(TAG, "SPI SRAM memory test OK");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
esp_err_t esp_spiram_init()
|
||||
{
|
||||
//Enable external RAM in MMU
|
||||
cache_sram_mmu_set( 0, 0, SOC_EXTRAM_DATA_LOW, 0, 32, 128 );
|
||||
//Flush and enable icache for APP CPU
|
||||
#if !CONFIG_FREERTOS_UNICORE
|
||||
DPORT_CLEAR_PERI_REG_MASK(DPORT_APP_CACHE_CTRL1_REG, DPORT_APP_CACHE_MASK_DRAM1);
|
||||
cache_sram_mmu_set( 1, 0, SOC_EXTRAM_DATA_LOW, 0, 32, 128 );
|
||||
#endif
|
||||
|
||||
esp_err_t r;
|
||||
r = psram_enable(PSRAM_SPEED, PSRAM_MODE);
|
||||
if (r != ESP_OK) {
|
||||
ESP_EARLY_LOGE(TAG, "SPI RAM enabled but initialization failed. Bailing out.");
|
||||
return r;
|
||||
}
|
||||
|
||||
ESP_EARLY_LOGI(TAG, "SPI RAM mode: %s", PSRAM_SPEED == PSRAM_CACHE_F40M_S40M ? "flash 40m sram 40m" : \
|
||||
PSRAM_SPEED == PSRAM_CACHE_F80M_S40M ? "flash 80m sram 40m" : \
|
||||
PSRAM_SPEED == PSRAM_CACHE_F80M_S80M ? "flash 80m sram 80m" : "ERROR");
|
||||
ESP_EARLY_LOGI(TAG, "PSRAM initialized, cache is in %s mode.", \
|
||||
(PSRAM_MODE==PSRAM_VADDR_MODE_EVENODD)?"even/odd (2-core)": \
|
||||
(PSRAM_MODE==PSRAM_VADDR_MODE_LOWHIGH)?"low/high (2-core)": \
|
||||
(PSRAM_MODE==PSRAM_VADDR_MODE_NORMAL)?"normal (1-core)":"ERROR");
|
||||
spiram_inited=true;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
size_t esp_spiram_get_size()
|
||||
{
|
||||
return CONFIG_SPIRAM_SIZE;
|
||||
}
|
||||
|
||||
/*
|
||||
Before flushing the cache, if psram is enabled as a memory-mapped thing, we need to write back the data in the cache to the psram first,
|
||||
otherwise it will get lost. For now, we just read 64/128K of random PSRAM memory to do this.
|
||||
*/
|
||||
void IRAM_ATTR esp_spiram_writeback_cache()
|
||||
{
|
||||
int x;
|
||||
volatile int i=0;
|
||||
volatile uint8_t *psram=(volatile uint8_t*)SOC_EXTRAM_DATA_LOW;
|
||||
int cache_was_disabled=0;
|
||||
|
||||
if (!spiram_inited) return;
|
||||
|
||||
//We need cache enabled for this to work. Re-enable it if needed; make sure we
|
||||
//disable it again on exit as well.
|
||||
if (DPORT_REG_GET_BIT(DPORT_PRO_CACHE_CTRL_REG, DPORT_PRO_CACHE_ENABLE)==0) {
|
||||
cache_was_disabled|=(1<<0);
|
||||
DPORT_SET_PERI_REG_BITS(DPORT_PRO_CACHE_CTRL_REG, 1, 1, DPORT_PRO_CACHE_ENABLE_S);
|
||||
}
|
||||
#ifndef CONFIG_FREERTOS_UNICORE
|
||||
if (DPORT_REG_GET_BIT(DPORT_APP_CACHE_CTRL_REG, DPORT_APP_CACHE_ENABLE)==0) {
|
||||
cache_was_disabled|=(1<<1);
|
||||
DPORT_SET_PERI_REG_BITS(DPORT_APP_CACHE_CTRL_REG, 1, 1, DPORT_APP_CACHE_ENABLE_S);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if CONFIG_FREERTOS_UNICORE
|
||||
for (x=0; x<1024*64; x+=32) {
|
||||
i+=psram[x];
|
||||
}
|
||||
#else
|
||||
/*
|
||||
Note: this assumes the amount of external RAM is >2M. If it is 2M or less, what this code does is undefined. If
|
||||
we ever support external RAM chips of 2M or smaller, this may need adjusting.
|
||||
*/
|
||||
for (x=0; x<1024*64; x+=32) {
|
||||
i+=psram[x];
|
||||
i+=psram[x+(1024*1024*2)+(1024*64)]; //address picked to also clear cache of app cpu in low/high mode
|
||||
}
|
||||
#endif
|
||||
|
||||
if (cache_was_disabled&(1<<0)) {
|
||||
while (DPORT_GET_PERI_REG_BITS2(DPORT_PRO_DCACHE_DBUG0_REG, DPORT_PRO_CACHE_STATE, DPORT_PRO_CACHE_STATE_S) != 1) ;
|
||||
DPORT_SET_PERI_REG_BITS(DPORT_PRO_CACHE_CTRL_REG, 1, 0, DPORT_PRO_CACHE_ENABLE_S);
|
||||
}
|
||||
#ifndef CONFIG_FREERTOS_UNICORE
|
||||
if (cache_was_disabled&(1<<1)) {
|
||||
while (DPORT_GET_PERI_REG_BITS2(DPORT_APP_DCACHE_DBUG0_REG, DPORT_APP_CACHE_STATE, DPORT_APP_CACHE_STATE_S) != 1);
|
||||
DPORT_SET_PERI_REG_BITS(DPORT_APP_CACHE_CTRL_REG, 1, 0, DPORT_APP_CACHE_ENABLE_S);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif
|
@ -1,19 +0,0 @@
|
||||
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#ifndef SPI_RAM_H
|
||||
#define SPI_RAM_H
|
||||
|
||||
void enable_spi_sram();
|
||||
|
||||
#endif
|
638
components/esp32/spiram_psram.c
Normal file
638
components/esp32/spiram_psram.c
Normal file
@ -0,0 +1,638 @@
|
||||
/*
|
||||
Driver bits for PSRAM chips (at the moment only the ESP-PSRAM32 chip).
|
||||
*/
|
||||
|
||||
// Copyright 2013-2017 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
|
||||
#include "sdkconfig.h"
|
||||
#include "string.h"
|
||||
#include "esp_attr.h"
|
||||
#include "esp_err.h"
|
||||
#include "esp_types.h"
|
||||
#include "spiram_psram.h"
|
||||
#include "rom/ets_sys.h"
|
||||
#include "rom/spi_flash.h"
|
||||
#include "rom/gpio.h"
|
||||
#include "rom/cache.h"
|
||||
#include "soc/io_mux_reg.h"
|
||||
#include "soc/dport_reg.h"
|
||||
#include "soc/gpio_sig_map.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "driver/spi_common.h"
|
||||
|
||||
#if CONFIG_SPIRAM_SUPPORT
|
||||
|
||||
//Commands for PSRAM chip
|
||||
#define PSRAM_READ 0x03
|
||||
#define PSRAM_FAST_READ 0x0B
|
||||
#define PSRAM_FAST_READ_DUMMY 0x3
|
||||
#define PSRAM_FAST_READ_QUAD 0xEB
|
||||
#define PSRAM_WRITE 0x02
|
||||
#define PSRAM_QUAD_WRITE 0x38
|
||||
#define PSRAM_ENTER_QMODE 0x35
|
||||
#define PSRAM_EXIT_QMODE 0xF5
|
||||
#define PSRAM_RESET_EN 0x66
|
||||
#define PSRAM_RESET 0x99
|
||||
#define PSRAM_SET_BURST_LEN 0xC0
|
||||
#define PSRAM_DEVICE_ID 0x9F
|
||||
|
||||
#if CONFIG_SPIRAM_TYPE_ESPPSRAM32
|
||||
|
||||
#define PSRAM_MFG_ID_M 0xff
|
||||
#define PSRAM_MFG_ID_S 8
|
||||
#define PSRAM_MFG_ID_V 0x5d
|
||||
|
||||
#endif
|
||||
|
||||
// IO-pins for PSRAM. These need to be in the VDD_SIO power domain because all chips we
|
||||
// currently support are 1.8V parts.
|
||||
// WARNING: PSRAM shares all but the CS and CLK pins with the flash, so these defines
|
||||
// hardcode the flash pins as well, making this code incompatible with either a setup
|
||||
// that has the flash on non-standard pins or ESP32s with built-in flash.
|
||||
#define FLASH_CLK_IO 6 //Psram clock is a delayed version of this in 40MHz mode
|
||||
#define FLASH_CS_IO 11
|
||||
#define PSRAM_CLK_IO 17
|
||||
#define PSRAM_CS_IO 16
|
||||
#define PSRAM_SPIQ_IO 7
|
||||
#define PSRAM_SPID_IO 8
|
||||
#define PSRAM_SPIWP_IO 10
|
||||
#define PSRAM_SPIHD_IO 9
|
||||
|
||||
#define PSRAM_IO_MATRIX_DUMMY_40M 1
|
||||
#define PSRAM_IO_MATRIX_DUMMY_80M 2
|
||||
|
||||
#if CONFIG_FLASHMODE_QIO
|
||||
#define SPI_CACHE_DUMMY SPI0_R_QIO_DUMMY_CYCLELEN //qio 3
|
||||
#elif CONFIG_FLASHMODE_QOUT
|
||||
#define SPI_CACHE_DUMMY SPI0_R_FAST_DUMMY_CYCLELEN //qout 7
|
||||
#elif CONFIG_FLASHMODE_DIO
|
||||
#define SPI_CACHE_DUMMY SPI0_R_DIO_DUMMY_CYCLELEN //dio 3
|
||||
#elif CONFIG_FLASHMODE_DOUT
|
||||
#define SPI_CACHE_DUMMY SPI0_R_FAST_DUMMY_CYCLELEN //dout 7
|
||||
#endif
|
||||
|
||||
|
||||
typedef enum {
|
||||
PSRAM_SPI_1 = 0x1,
|
||||
PSRAM_SPI_2,
|
||||
PSRAM_SPI_3,
|
||||
PSRAM_SPI_MAX ,
|
||||
} psram_spi_num_t;
|
||||
|
||||
static psram_cache_mode_t s_psram_mode = PSRAM_CACHE_MAX;
|
||||
|
||||
//For now, we only use F40M + S40M, and we don't have to go through gpio matrix
|
||||
#define ENABLE_GPIO_MATRIX_SPI 1
|
||||
|
||||
/* dummy_len_plus values defined in ROM for SPI flash configuration */
|
||||
extern uint8_t g_rom_spiflash_dummy_len_plus[];
|
||||
|
||||
static int extra_dummy = 0;
|
||||
|
||||
typedef enum {
|
||||
PSRAM_CMD_QPI,
|
||||
PSRAM_CMD_SPI,
|
||||
} psram_cmd_mode_t;
|
||||
|
||||
typedef struct {
|
||||
uint16_t cmd; /*!< Command value */
|
||||
uint16_t cmdBitLen; /*!< Command byte length*/
|
||||
uint32_t *addr; /*!< Point to address value*/
|
||||
uint16_t addrBitLen; /*!< Address byte length*/
|
||||
uint32_t *txData; /*!< Point to send data buffer*/
|
||||
uint16_t txDataBitLen; /*!< Send data byte length.*/
|
||||
uint32_t *rxData; /*!< Point to recevie data buffer*/
|
||||
uint16_t rxDataBitLen; /*!< Recevie Data byte length.*/
|
||||
uint32_t dummyBitLen;
|
||||
} psram_cmd_t;
|
||||
|
||||
static void IRAM_ATTR psram_cache_init(psram_cache_mode_t psram_cache_mode, psram_vaddr_mode_t vaddrmode);
|
||||
|
||||
static void psram_clear_spi_fifo(psram_spi_num_t spi_num)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < 16; i++) {
|
||||
WRITE_PERI_REG(SPI_W0_REG(spi_num)+i*4, 0);
|
||||
}
|
||||
}
|
||||
|
||||
//set basic SPI write mode
|
||||
static void psram_set_basic_write_mode(psram_spi_num_t spi_num)
|
||||
{
|
||||
CLEAR_PERI_REG_MASK(SPI_USER_REG(spi_num), SPI_FWRITE_QIO);
|
||||
CLEAR_PERI_REG_MASK(SPI_USER_REG(spi_num), SPI_FWRITE_DIO);
|
||||
CLEAR_PERI_REG_MASK(SPI_USER_REG(spi_num), SPI_FWRITE_QUAD);
|
||||
CLEAR_PERI_REG_MASK(SPI_USER_REG(spi_num), SPI_FWRITE_DUAL);
|
||||
}
|
||||
//set QPI write mode
|
||||
static void psram_set_qio_write_mode(psram_spi_num_t spi_num)
|
||||
{
|
||||
SET_PERI_REG_MASK(SPI_USER_REG(spi_num), SPI_FWRITE_QIO);
|
||||
CLEAR_PERI_REG_MASK(SPI_USER_REG(spi_num), SPI_FWRITE_DIO);
|
||||
CLEAR_PERI_REG_MASK(SPI_USER_REG(spi_num), SPI_FWRITE_QUAD);
|
||||
CLEAR_PERI_REG_MASK(SPI_USER_REG(spi_num), SPI_FWRITE_DUAL);
|
||||
}
|
||||
//set QPI read mode
|
||||
static void psram_set_qio_read_mode(psram_spi_num_t spi_num)
|
||||
{
|
||||
SET_PERI_REG_MASK(SPI_CTRL_REG(spi_num), SPI_FREAD_QIO);
|
||||
CLEAR_PERI_REG_MASK(SPI_CTRL_REG(spi_num), SPI_FREAD_QUAD);
|
||||
CLEAR_PERI_REG_MASK(SPI_CTRL_REG(spi_num), SPI_FREAD_DUAL);
|
||||
CLEAR_PERI_REG_MASK(SPI_CTRL_REG(spi_num), SPI_FREAD_DIO);
|
||||
}
|
||||
//set SPI read mode
|
||||
static void psram_set_basic_read_mode(psram_spi_num_t spi_num)
|
||||
{
|
||||
CLEAR_PERI_REG_MASK(SPI_CTRL_REG(spi_num), SPI_FREAD_QIO);
|
||||
CLEAR_PERI_REG_MASK(SPI_CTRL_REG(spi_num), SPI_FREAD_QUAD);
|
||||
CLEAR_PERI_REG_MASK(SPI_CTRL_REG(spi_num), SPI_FREAD_DUAL);
|
||||
CLEAR_PERI_REG_MASK(SPI_CTRL_REG(spi_num), SPI_FREAD_DIO);
|
||||
}
|
||||
|
||||
|
||||
//start sending cmd/addr and optionally, receiving data
|
||||
static void IRAM_ATTR psram_cmd_recv_start(psram_spi_num_t spi_num, uint32_t* pRxData, uint16_t rxByteLen,
|
||||
psram_cmd_mode_t cmd_mode)
|
||||
{
|
||||
//get cs1
|
||||
CLEAR_PERI_REG_MASK(SPI_PIN_REG(PSRAM_SPI_1), SPI_CS1_DIS_M);
|
||||
SET_PERI_REG_MASK(SPI_PIN_REG(PSRAM_SPI_1), SPI_CS0_DIS_M);
|
||||
|
||||
uint32_t mode_backup = (READ_PERI_REG(SPI_USER_REG(spi_num)) >> SPI_FWRITE_DUAL_S) & 0xf;
|
||||
uint32_t rd_mode_backup = READ_PERI_REG(SPI_CTRL_REG(spi_num)) & (SPI_FREAD_DIO_M | SPI_FREAD_DUAL_M | SPI_FREAD_QUAD_M | SPI_FREAD_QIO_M);
|
||||
if (cmd_mode == PSRAM_CMD_SPI) {
|
||||
psram_set_basic_write_mode(spi_num);
|
||||
psram_set_basic_read_mode(spi_num);
|
||||
} else if (cmd_mode == PSRAM_CMD_QPI) {
|
||||
psram_set_qio_write_mode(spi_num);
|
||||
psram_set_qio_read_mode(spi_num);
|
||||
}
|
||||
|
||||
//Wait for SPI0 to idle
|
||||
while ( READ_PERI_REG(SPI_EXT2_REG(0)) != 0);
|
||||
DPORT_SET_PERI_REG_MASK(DPORT_HOST_INF_SEL_REG, 1 << 14);
|
||||
|
||||
// Start send data
|
||||
SET_PERI_REG_MASK(SPI_CMD_REG(spi_num), SPI_USR);
|
||||
while ((READ_PERI_REG(SPI_CMD_REG(spi_num)) & SPI_USR));
|
||||
DPORT_CLEAR_PERI_REG_MASK(DPORT_HOST_INF_SEL_REG, 1 << 14);
|
||||
|
||||
//recover spi mode
|
||||
SET_PERI_REG_BITS(SPI_USER_REG(spi_num), (pRxData?SPI_FWRITE_DUAL_M:0xf), mode_backup, SPI_FWRITE_DUAL_S);
|
||||
CLEAR_PERI_REG_MASK(SPI_CTRL_REG(spi_num), (SPI_FREAD_DIO_M|SPI_FREAD_DUAL_M|SPI_FREAD_QUAD_M|SPI_FREAD_QIO_M));
|
||||
SET_PERI_REG_MASK(SPI_CTRL_REG(spi_num), rd_mode_backup);
|
||||
|
||||
//return cs to cs0
|
||||
SET_PERI_REG_MASK(SPI_PIN_REG(PSRAM_SPI_1), SPI_CS1_DIS_M);
|
||||
CLEAR_PERI_REG_MASK(SPI_PIN_REG(PSRAM_SPI_1), SPI_CS0_DIS_M);
|
||||
|
||||
if (pRxData) {
|
||||
int idx = 0;
|
||||
// Read data out
|
||||
do {
|
||||
*pRxData++ = READ_PERI_REG(SPI_W0_REG(spi_num) + (idx << 2));
|
||||
} while (++idx < ((rxByteLen / 4) + ((rxByteLen % 4) ? 1 : 0)));
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t backup_usr[3];
|
||||
static uint32_t backup_usr1[3];
|
||||
static uint32_t backup_usr2[3];
|
||||
|
||||
|
||||
|
||||
//setup spi command/addr/data/dummy in user mode
|
||||
static int psram_cmd_config(psram_spi_num_t spi_num, psram_cmd_t* pInData)
|
||||
{
|
||||
while (READ_PERI_REG(SPI_CMD_REG(spi_num)) & SPI_USR);
|
||||
backup_usr[spi_num]=READ_PERI_REG(SPI_USER_REG(spi_num));
|
||||
backup_usr1[spi_num]=READ_PERI_REG(SPI_USER1_REG(spi_num));
|
||||
backup_usr2[spi_num]=READ_PERI_REG(SPI_USER2_REG(spi_num));
|
||||
// Set command by user.
|
||||
if (pInData->cmdBitLen != 0) {
|
||||
// Max command length 16 bits.
|
||||
SET_PERI_REG_BITS(SPI_USER2_REG(spi_num), SPI_USR_COMMAND_BITLEN, pInData->cmdBitLen - 1,
|
||||
SPI_USR_COMMAND_BITLEN_S);
|
||||
// Enable command
|
||||
SET_PERI_REG_MASK(SPI_USER_REG(spi_num), SPI_USR_COMMAND);
|
||||
// Load command,bit15-0 is cmd value.
|
||||
SET_PERI_REG_BITS(SPI_USER2_REG(spi_num), SPI_USR_COMMAND_VALUE, pInData->cmd, SPI_USR_COMMAND_VALUE_S);
|
||||
} else {
|
||||
CLEAR_PERI_REG_MASK(SPI_USER_REG(spi_num), SPI_USR_COMMAND);
|
||||
SET_PERI_REG_BITS(SPI_USER2_REG(spi_num), SPI_USR_COMMAND_BITLEN, 0, SPI_USR_COMMAND_BITLEN_S);
|
||||
}
|
||||
// Set Address by user.
|
||||
if (pInData->addrBitLen != 0) {
|
||||
SET_PERI_REG_BITS(SPI_USER1_REG(spi_num), SPI_USR_ADDR_BITLEN, (pInData->addrBitLen - 1), SPI_USR_ADDR_BITLEN_S);
|
||||
// Enable address
|
||||
SET_PERI_REG_MASK(SPI_USER_REG(spi_num), SPI_USR_ADDR);
|
||||
// Set address
|
||||
WRITE_PERI_REG(SPI_ADDR_REG(spi_num), *pInData->addr);
|
||||
} else {
|
||||
CLEAR_PERI_REG_MASK(SPI_USER_REG(spi_num), SPI_USR_ADDR);
|
||||
SET_PERI_REG_BITS(SPI_USER1_REG(spi_num), SPI_USR_ADDR_BITLEN, 0, SPI_USR_ADDR_BITLEN_S);
|
||||
}
|
||||
// Set data by user.
|
||||
uint32_t* p_tx_val = pInData->txData;
|
||||
if (pInData->txDataBitLen != 0) {
|
||||
// Enable MOSI
|
||||
SET_PERI_REG_MASK(SPI_USER_REG(spi_num), SPI_USR_MOSI);
|
||||
// Load send buffer
|
||||
int len = (pInData->txDataBitLen + 31) / 32;
|
||||
if (p_tx_val != NULL) {
|
||||
memcpy((void*)SPI_W0_REG(spi_num), p_tx_val, len * 4);
|
||||
}
|
||||
// Set data send buffer length.Max data length 64 bytes.
|
||||
SET_PERI_REG_BITS(SPI_MOSI_DLEN_REG(spi_num), SPI_USR_MOSI_DBITLEN, (pInData->txDataBitLen - 1),
|
||||
SPI_USR_MOSI_DBITLEN_S);
|
||||
} else {
|
||||
CLEAR_PERI_REG_MASK(SPI_USER_REG(spi_num), SPI_USR_MOSI);
|
||||
SET_PERI_REG_BITS(SPI_MOSI_DLEN_REG(spi_num), SPI_USR_MOSI_DBITLEN, 0, SPI_USR_MOSI_DBITLEN_S);
|
||||
}
|
||||
// Set rx data by user.
|
||||
if (pInData->rxDataBitLen != 0) {
|
||||
// Enable MOSI
|
||||
SET_PERI_REG_MASK(SPI_USER_REG(spi_num), SPI_USR_MISO);
|
||||
// Set data send buffer length.Max data length 64 bytes.
|
||||
SET_PERI_REG_BITS(SPI_MISO_DLEN_REG(spi_num), SPI_USR_MISO_DBITLEN, (pInData->rxDataBitLen - 1),
|
||||
SPI_USR_MISO_DBITLEN_S);
|
||||
} else {
|
||||
CLEAR_PERI_REG_MASK(SPI_USER_REG(spi_num), SPI_USR_MISO);
|
||||
SET_PERI_REG_BITS(SPI_MISO_DLEN_REG(spi_num), SPI_USR_MISO_DBITLEN, 0, SPI_USR_MISO_DBITLEN_S);
|
||||
}
|
||||
if (pInData->dummyBitLen != 0) {
|
||||
SET_PERI_REG_MASK(SPI_USER_REG(PSRAM_SPI_1), SPI_USR_DUMMY); // dummy en
|
||||
SET_PERI_REG_BITS(SPI_USER1_REG(PSRAM_SPI_1), SPI_USR_DUMMY_CYCLELEN_V, pInData->dummyBitLen - 1,
|
||||
SPI_USR_DUMMY_CYCLELEN_S); //DUMMY
|
||||
} else {
|
||||
CLEAR_PERI_REG_MASK(SPI_USER_REG(PSRAM_SPI_1), SPI_USR_DUMMY); // dummy en
|
||||
SET_PERI_REG_BITS(SPI_USER1_REG(PSRAM_SPI_1), SPI_USR_DUMMY_CYCLELEN_V, 0, SPI_USR_DUMMY_CYCLELEN_S); //DUMMY
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void psram_cmd_end(int spi_num) {
|
||||
while (READ_PERI_REG(SPI_CMD_REG(spi_num)) & SPI_USR);
|
||||
WRITE_PERI_REG(SPI_USER_REG(spi_num), backup_usr[spi_num]);
|
||||
WRITE_PERI_REG(SPI_USER1_REG(spi_num), backup_usr1[spi_num]);
|
||||
WRITE_PERI_REG(SPI_USER2_REG(spi_num), backup_usr2[spi_num]);
|
||||
}
|
||||
|
||||
//exit QPI mode(set back to SPI mode)
|
||||
static void psram_disable_qio_mode(psram_spi_num_t spi_num)
|
||||
{
|
||||
psram_cmd_t ps_cmd;
|
||||
uint32_t cmd_exit_qpi;
|
||||
switch (s_psram_mode) {
|
||||
case PSRAM_CACHE_F80M_S80M:
|
||||
cmd_exit_qpi = PSRAM_EXIT_QMODE;
|
||||
ps_cmd.txDataBitLen = 8;
|
||||
break;
|
||||
case PSRAM_CACHE_F80M_S40M:
|
||||
case PSRAM_CACHE_F40M_S40M:
|
||||
default:
|
||||
cmd_exit_qpi = PSRAM_EXIT_QMODE << 8;
|
||||
ps_cmd.txDataBitLen = 16;
|
||||
break;
|
||||
}
|
||||
ps_cmd.txData = &cmd_exit_qpi;
|
||||
ps_cmd.cmd = 0;
|
||||
ps_cmd.cmdBitLen = 0;
|
||||
ps_cmd.addr = 0;
|
||||
ps_cmd.addrBitLen = 0;
|
||||
ps_cmd.rxData = NULL;
|
||||
ps_cmd.rxDataBitLen = 0;
|
||||
ps_cmd.dummyBitLen = 0;
|
||||
psram_cmd_config(spi_num, &ps_cmd);
|
||||
psram_cmd_recv_start(spi_num, NULL, 0, PSRAM_CMD_QPI);
|
||||
psram_cmd_end(spi_num);
|
||||
}
|
||||
|
||||
//read psram id
|
||||
static void psram_read_id(uint32_t* dev_id)
|
||||
{
|
||||
psram_spi_num_t spi_num = PSRAM_SPI_1;
|
||||
psram_disable_qio_mode(spi_num);
|
||||
uint32_t addr = (PSRAM_DEVICE_ID << 24) | 0;
|
||||
uint32_t dummy_bits = 0;
|
||||
psram_cmd_t ps_cmd;
|
||||
switch (s_psram_mode) {
|
||||
case PSRAM_CACHE_F80M_S80M:
|
||||
dummy_bits = 0 + extra_dummy;
|
||||
ps_cmd.cmdBitLen = 0;
|
||||
break;
|
||||
case PSRAM_CACHE_F80M_S40M:
|
||||
case PSRAM_CACHE_F40M_S40M:
|
||||
default:
|
||||
dummy_bits = 0 + extra_dummy;
|
||||
ps_cmd.cmdBitLen = 2; //this two bits is used to delay 2 clock cycle
|
||||
break;
|
||||
}
|
||||
ps_cmd.cmd = 0;
|
||||
ps_cmd.addr = &addr;
|
||||
ps_cmd.addrBitLen = 4 * 8;
|
||||
ps_cmd.txDataBitLen = 0;
|
||||
ps_cmd.txData = NULL;
|
||||
ps_cmd.rxDataBitLen = 4 * 8;
|
||||
ps_cmd.rxData = dev_id;
|
||||
ps_cmd.dummyBitLen = dummy_bits;
|
||||
psram_cmd_config(spi_num, &ps_cmd);
|
||||
psram_clear_spi_fifo(spi_num);
|
||||
psram_cmd_recv_start(spi_num, ps_cmd.rxData, ps_cmd.rxDataBitLen / 8, PSRAM_CMD_SPI);
|
||||
psram_cmd_end(spi_num);
|
||||
}
|
||||
|
||||
//enter QPI mode
|
||||
static esp_err_t IRAM_ATTR psram_enable_qio_mode(psram_spi_num_t spi_num)
|
||||
{
|
||||
psram_cmd_t ps_cmd;
|
||||
uint32_t addr = (PSRAM_ENTER_QMODE << 24) | 0;
|
||||
switch (s_psram_mode) {
|
||||
case PSRAM_CACHE_F80M_S80M:
|
||||
ps_cmd.cmdBitLen = 0;
|
||||
break;
|
||||
case PSRAM_CACHE_F80M_S40M:
|
||||
case PSRAM_CACHE_F40M_S40M:
|
||||
default:
|
||||
ps_cmd.cmdBitLen = 2;
|
||||
break;
|
||||
}
|
||||
ps_cmd.cmd = 0;
|
||||
ps_cmd.addr = &addr;
|
||||
ps_cmd.addrBitLen = 8;
|
||||
ps_cmd.txData = NULL;
|
||||
ps_cmd.txDataBitLen = 0;
|
||||
ps_cmd.rxData = NULL;
|
||||
ps_cmd.rxDataBitLen = 0;
|
||||
ps_cmd.dummyBitLen = 0;
|
||||
psram_cmd_config(spi_num, &ps_cmd);
|
||||
psram_cmd_recv_start(spi_num, NULL, 0, PSRAM_CMD_SPI);
|
||||
psram_cmd_end(spi_num);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
//spi param init for psram
|
||||
void IRAM_ATTR psram_spi_init(psram_spi_num_t spi_num, psram_cache_mode_t mode)
|
||||
{
|
||||
uint8_t i, k;
|
||||
CLEAR_PERI_REG_MASK(SPI_SLAVE_REG(spi_num), SPI_TRANS_DONE << 5);
|
||||
SET_PERI_REG_MASK(SPI_USER_REG(spi_num), SPI_CS_SETUP);
|
||||
// SPI_CPOL & SPI_CPHA
|
||||
CLEAR_PERI_REG_MASK(SPI_PIN_REG(spi_num), SPI_CK_IDLE_EDGE);
|
||||
CLEAR_PERI_REG_MASK(SPI_USER_REG(spi_num), SPI_CK_OUT_EDGE);
|
||||
// SPI bit order
|
||||
CLEAR_PERI_REG_MASK(SPI_CTRL_REG(spi_num), SPI_WR_BIT_ORDER);
|
||||
CLEAR_PERI_REG_MASK(SPI_CTRL_REG(spi_num), SPI_RD_BIT_ORDER);
|
||||
// SPI bit order
|
||||
CLEAR_PERI_REG_MASK(SPI_USER_REG(spi_num), SPI_DOUTDIN);
|
||||
// May be not must to do.
|
||||
WRITE_PERI_REG(SPI_USER1_REG(spi_num), 0);
|
||||
// SPI mode type
|
||||
CLEAR_PERI_REG_MASK(SPI_SLAVE_REG(spi_num), SPI_SLAVE_MODE);
|
||||
// Set SPI speed for non-80M mode. (80M mode uses APB clock directly.)
|
||||
if (mode!=PSRAM_CACHE_F80M_S80M) {
|
||||
i = 1; //Pre-divider
|
||||
k = 2; //Main divider. Divide by 2 so we get 40MHz
|
||||
//clear bit 31, set SPI clock div
|
||||
CLEAR_PERI_REG_MASK(SPI_CLOCK_REG(spi_num), SPI_CLK_EQU_SYSCLK);
|
||||
WRITE_PERI_REG(SPI_CLOCK_REG(spi_num),
|
||||
(((i - 1) & SPI_CLKDIV_PRE) << SPI_CLKDIV_PRE_S) |
|
||||
(((k - 1) & SPI_CLKCNT_N) << SPI_CLKCNT_N_S) |
|
||||
((((k + 1) / 2 - 1) & SPI_CLKCNT_H) << SPI_CLKCNT_H_S) | //50% duty cycle
|
||||
(((k - 1) & SPI_CLKCNT_L) << SPI_CLKCNT_L_S));
|
||||
}
|
||||
// Enable MOSI
|
||||
SET_PERI_REG_MASK(SPI_USER_REG(spi_num), SPI_CS_SETUP | SPI_CS_HOLD | SPI_USR_MOSI);
|
||||
memset((void*)SPI_W0_REG(spi_num), 0, 16 * 4);
|
||||
}
|
||||
|
||||
static void IRAM_ATTR psram_gpio_config(psram_cache_mode_t mode)
|
||||
{
|
||||
gpio_matrix_out(FLASH_CLK_IO, SPICLK_OUT_IDX, 0, 0);
|
||||
gpio_matrix_out(FLASH_CS_IO, SPICS0_OUT_IDX, 0, 0);
|
||||
gpio_matrix_out(PSRAM_SPIQ_IO, SPIQ_OUT_IDX, 0, 0);
|
||||
gpio_matrix_in(PSRAM_SPIQ_IO, SPIQ_IN_IDX, 0);
|
||||
gpio_matrix_out(PSRAM_SPID_IO, SPID_OUT_IDX, 0, 0);
|
||||
gpio_matrix_in(PSRAM_SPID_IO, SPID_IN_IDX, 0);
|
||||
gpio_matrix_out(PSRAM_SPIWP_IO, SPIWP_OUT_IDX, 0, 0);
|
||||
gpio_matrix_in(PSRAM_SPIWP_IO, SPIWP_IN_IDX, 0);
|
||||
gpio_matrix_out(PSRAM_SPIHD_IO, SPIHD_OUT_IDX, 0, 0);
|
||||
gpio_matrix_in(PSRAM_SPIHD_IO, SPIHD_IN_IDX, 0);
|
||||
|
||||
switch (mode) {
|
||||
case PSRAM_CACHE_F80M_S40M:
|
||||
extra_dummy = PSRAM_IO_MATRIX_DUMMY_40M;
|
||||
g_rom_spiflash_dummy_len_plus[1] = PSRAM_IO_MATRIX_DUMMY_40M;
|
||||
SET_PERI_REG_BITS(SPI_USER1_REG(0), SPI_USR_DUMMY_CYCLELEN_V, SPI_CACHE_DUMMY + PSRAM_IO_MATRIX_DUMMY_80M, SPI_USR_DUMMY_CYCLELEN_S); //DUMMY
|
||||
break;
|
||||
case PSRAM_CACHE_F80M_S80M:
|
||||
extra_dummy = PSRAM_IO_MATRIX_DUMMY_80M;
|
||||
g_rom_spiflash_dummy_len_plus[1] = PSRAM_IO_MATRIX_DUMMY_80M;
|
||||
SET_PERI_REG_BITS(SPI_USER1_REG(0), SPI_USR_DUMMY_CYCLELEN_V, SPI_CACHE_DUMMY + PSRAM_IO_MATRIX_DUMMY_80M, SPI_USR_DUMMY_CYCLELEN_S); //DUMMY
|
||||
break;
|
||||
case PSRAM_CACHE_F40M_S40M:
|
||||
extra_dummy = PSRAM_IO_MATRIX_DUMMY_40M;
|
||||
g_rom_spiflash_dummy_len_plus[1] = PSRAM_IO_MATRIX_DUMMY_40M;
|
||||
SET_PERI_REG_BITS(SPI_USER1_REG(0), SPI_USR_DUMMY_CYCLELEN_V, SPI_CACHE_DUMMY + PSRAM_IO_MATRIX_DUMMY_40M, SPI_USR_DUMMY_CYCLELEN_S); //DUMMY
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
SET_PERI_REG_MASK(SPI_USER_REG(0), SPI_USR_DUMMY); // dummy en
|
||||
|
||||
//select pin function gpio
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA0_U, 2);
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA1_U, 2);
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA2_U, 2);
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA3_U, 2);
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CLK_U, 2);
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CMD_U, 2);
|
||||
}
|
||||
|
||||
//psram gpio init , different working frequency we have different solutions
|
||||
esp_err_t IRAM_ATTR psram_enable(psram_cache_mode_t mode, psram_vaddr_mode_t vaddrmode) //psram init
|
||||
{
|
||||
/* note: If the third mode(80Mhz+80Mhz) is enabled, VSPI port will be occupied by the system,
|
||||
Application code should never touch VSPI hardware in this case. We try to stop applications
|
||||
from doing this using the drivers by claiming the port for ourselves*/
|
||||
if (mode == PSRAM_CACHE_F80M_S80M) {
|
||||
bool r=spicommon_periph_claim(VSPI_HOST);
|
||||
if (!r) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
}
|
||||
|
||||
WRITE_PERI_REG(GPIO_ENABLE_W1TC_REG, BIT(PSRAM_CLK_IO) | BIT(PSRAM_CS_IO)); //DISABLE OUPUT FOR IO16/17
|
||||
assert(mode < PSRAM_CACHE_MAX && "we don't support any other mode for now.");
|
||||
s_psram_mode = mode;
|
||||
|
||||
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI_CLK_EN);
|
||||
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI_RST);
|
||||
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI_CLK_EN_1);
|
||||
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI_RST_1);
|
||||
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI_CLK_EN_2);
|
||||
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI_RST_2);
|
||||
|
||||
WRITE_PERI_REG(SPI_EXT3_REG(0), 0x1);
|
||||
CLEAR_PERI_REG_MASK(SPI_USER_REG(PSRAM_SPI_1), SPI_USR_PREP_HOLD_M);
|
||||
|
||||
switch (mode) {
|
||||
case PSRAM_CACHE_F80M_S80M:
|
||||
psram_spi_init(PSRAM_SPI_1, mode);
|
||||
CLEAR_PERI_REG_MASK(SPI_USER_REG(PSRAM_SPI_1), SPI_CS_HOLD);
|
||||
gpio_matrix_out(PSRAM_CS_IO, SPICS1_OUT_IDX, 0, 0);
|
||||
gpio_matrix_out(PSRAM_CLK_IO, VSPICLK_OUT_IDX, 0, 0);
|
||||
//use spi3 clock,but use spi1 data/cs wires
|
||||
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);
|
||||
uint32_t spi_status;
|
||||
while (1) {
|
||||
spi_status = READ_PERI_REG(SPI_EXT2_REG(PSRAM_SPI_3));
|
||||
if (spi_status != 0 && spi_status != 1) {
|
||||
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, BIT(PSRAM_CS_IO)); //DPORT_SPI_CLK_EN
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PSRAM_CACHE_F80M_S40M:
|
||||
case PSRAM_CACHE_F40M_S40M:
|
||||
default:
|
||||
psram_spi_init(PSRAM_SPI_1, mode);
|
||||
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:
|
||||
GPIO6(SPI CLK) --> signal224(in then out) --> internal GPIO20 --> signal225(in then out) --> GPIO17(PSRAM CLK)
|
||||
*/
|
||||
gpio_matrix_in(FLASH_CLK_IO, SIG_IN_FUNC224_IDX, 0);
|
||||
gpio_matrix_out(20, SIG_IN_FUNC224_IDX, 0, 0);
|
||||
gpio_matrix_in(20, SIG_IN_FUNC225_IDX, 0);
|
||||
gpio_matrix_out(PSRAM_CLK_IO, SIG_IN_FUNC225_IDX, 0, 0);
|
||||
break;
|
||||
}
|
||||
CLEAR_PERI_REG_MASK(SPI_USER_REG(PSRAM_SPI_1), SPI_CS_SETUP_M);
|
||||
|
||||
#if ENABLE_GPIO_MATRIX_SPI
|
||||
psram_gpio_config(mode);
|
||||
#endif
|
||||
WRITE_PERI_REG(GPIO_ENABLE_W1TS_REG, BIT(PSRAM_CS_IO)| BIT(PSRAM_CLK_IO));
|
||||
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[PSRAM_CS_IO], 2);
|
||||
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[PSRAM_CLK_IO], 2);
|
||||
uint32_t id;
|
||||
psram_read_id(&id);
|
||||
if (((id >> PSRAM_MFG_ID_S) & PSRAM_MFG_ID_M) != PSRAM_MFG_ID_V) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
psram_enable_qio_mode(PSRAM_SPI_1);
|
||||
|
||||
psram_cache_init(mode, vaddrmode);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
//register initialization for sram cache params and r/w commands
|
||||
static void IRAM_ATTR psram_cache_init(psram_cache_mode_t psram_cache_mode, psram_vaddr_mode_t vaddrmode)
|
||||
{
|
||||
CLEAR_PERI_REG_MASK(SPI_CLOCK_REG(0), SPI_CLK_EQU_SYSCLK_M);
|
||||
SET_PERI_REG_BITS(SPI_CLOCK_REG(0), SPI_CLKDIV_PRE_V, 0, SPI_CLKDIV_PRE_S);
|
||||
SET_PERI_REG_BITS(SPI_CLOCK_REG(0), SPI_CLKCNT_N, 1, SPI_CLKCNT_N_S);
|
||||
SET_PERI_REG_BITS(SPI_CLOCK_REG(0), SPI_CLKCNT_H, 0, SPI_CLKCNT_H_S);
|
||||
SET_PERI_REG_BITS(SPI_CLOCK_REG(0), SPI_CLKCNT_L, 1, SPI_CLKCNT_L_S);
|
||||
|
||||
switch (psram_cache_mode) {
|
||||
case PSRAM_CACHE_F80M_S80M:
|
||||
CLEAR_PERI_REG_MASK(SPI_DATE_REG(0), BIT(31)); //flash 1 div clk,80+40;
|
||||
CLEAR_PERI_REG_MASK(SPI_DATE_REG(0), BIT(30)); //pre clk div , ONLY IF SPI/SRAM@ DIFFERENT SPEED,JUST FOR SPI0. FLASH DIV 2+SRAM DIV4
|
||||
WRITE_PERI_REG(SPI_CLOCK_REG(0), SPI_CLK_EQU_SYSCLK_M); //SET 1DIV CLOCK AND RESET OTHER PARAMS
|
||||
SET_PERI_REG_MASK(SPI_CACHE_SCTRL_REG(0), SPI_USR_RD_SRAM_DUMMY_M); //enable cache read dummy
|
||||
SET_PERI_REG_BITS(SPI_CACHE_SCTRL_REG(0), SPI_SRAM_DUMMY_CYCLELEN_V, PSRAM_FAST_READ_DUMMY + extra_dummy,
|
||||
SPI_SRAM_DUMMY_CYCLELEN_S); //dummy, psram cache : 40m--+1dummy,80m--+2dummy
|
||||
SET_PERI_REG_MASK(SPI_CACHE_SCTRL_REG(0), SPI_CACHE_SRAM_USR_RCMD_M); //enable user mode for cache read command
|
||||
break;
|
||||
case PSRAM_CACHE_F80M_S40M:
|
||||
SET_PERI_REG_MASK(SPI_DATE_REG(0), BIT(31)); //flash 1 div clk
|
||||
CLEAR_PERI_REG_MASK(SPI_DATE_REG(0), BIT(30)); //pre clk div , ONLY IF SPI/SRAM@ DIFFERENT SPEED,JUST FOR SPI0.
|
||||
SET_PERI_REG_MASK(SPI_CACHE_SCTRL_REG(0), SPI_USR_RD_SRAM_DUMMY_M); //enable cache read dummy
|
||||
SET_PERI_REG_BITS(SPI_CACHE_SCTRL_REG(0), SPI_SRAM_DUMMY_CYCLELEN_V, PSRAM_FAST_READ_DUMMY + extra_dummy,
|
||||
SPI_SRAM_DUMMY_CYCLELEN_S); //dummy, psram cache : 40m--+1dummy,80m--+2dummy
|
||||
SET_PERI_REG_MASK(SPI_CACHE_SCTRL_REG(0), SPI_CACHE_SRAM_USR_RCMD_M); //enable user mode for cache read command
|
||||
break;
|
||||
case PSRAM_CACHE_F40M_S40M:
|
||||
default:
|
||||
CLEAR_PERI_REG_MASK(SPI_DATE_REG(0), BIT(31)); //flash 1 div clk
|
||||
CLEAR_PERI_REG_MASK(SPI_DATE_REG(0), BIT(30)); //pre clk div
|
||||
SET_PERI_REG_MASK(SPI_CACHE_SCTRL_REG(0), SPI_USR_RD_SRAM_DUMMY_M); //enable cache read dummy
|
||||
SET_PERI_REG_BITS(SPI_CACHE_SCTRL_REG(0), SPI_SRAM_DUMMY_CYCLELEN_V, PSRAM_FAST_READ_DUMMY + extra_dummy,
|
||||
SPI_SRAM_DUMMY_CYCLELEN_S); //dummy, psram cache : 40m--+1dummy,80m--+2dummy
|
||||
SET_PERI_REG_MASK(SPI_CACHE_SCTRL_REG(0), SPI_CACHE_SRAM_USR_RCMD_M); //enable user mode for cache read command
|
||||
break;
|
||||
}
|
||||
SET_PERI_REG_MASK(SPI_CACHE_SCTRL_REG(0), SPI_CACHE_SRAM_USR_WCMD_M); // cache write command enable
|
||||
SET_PERI_REG_BITS(SPI_CACHE_SCTRL_REG(0), SPI_SRAM_ADDR_BITLEN_V, 23, SPI_SRAM_ADDR_BITLEN_S); //write address for cache command.
|
||||
SET_PERI_REG_MASK(SPI_CACHE_SCTRL_REG(0), SPI_USR_SRAM_QIO_M); //enable qio mode for cache command
|
||||
CLEAR_PERI_REG_MASK(SPI_CACHE_SCTRL_REG(0), SPI_USR_SRAM_DIO_M); //disable dio mode for cache command
|
||||
|
||||
|
||||
//config sram cache r/w command
|
||||
switch (psram_cache_mode) {
|
||||
case PSRAM_CACHE_F80M_S80M: //in this mode , no delay is needed
|
||||
SET_PERI_REG_BITS(SPI_SRAM_DWR_CMD_REG(0), SPI_CACHE_SRAM_USR_WR_CMD_BITLEN, 7,
|
||||
SPI_CACHE_SRAM_USR_WR_CMD_BITLEN_S);
|
||||
SET_PERI_REG_BITS(SPI_SRAM_DWR_CMD_REG(0), SPI_CACHE_SRAM_USR_WR_CMD_VALUE, PSRAM_QUAD_WRITE,
|
||||
SPI_CACHE_SRAM_USR_WR_CMD_VALUE_S); //0x38
|
||||
SET_PERI_REG_BITS(SPI_SRAM_DRD_CMD_REG(0), SPI_CACHE_SRAM_USR_RD_CMD_BITLEN_V, 7,
|
||||
SPI_CACHE_SRAM_USR_RD_CMD_BITLEN_S);
|
||||
SET_PERI_REG_BITS(SPI_SRAM_DRD_CMD_REG(0), SPI_CACHE_SRAM_USR_RD_CMD_VALUE_V, PSRAM_FAST_READ,
|
||||
SPI_CACHE_SRAM_USR_RD_CMD_VALUE_S); //0x0b
|
||||
break;
|
||||
case PSRAM_CACHE_F80M_S40M: //is sram is @40M, need 2 cycles of delay
|
||||
case PSRAM_CACHE_F40M_S40M:
|
||||
default:
|
||||
SET_PERI_REG_BITS(SPI_SRAM_DRD_CMD_REG(0), SPI_CACHE_SRAM_USR_RD_CMD_BITLEN_V, 15,
|
||||
SPI_CACHE_SRAM_USR_RD_CMD_BITLEN_S); //read command length, 2 bytes(1byte for delay),sending in qio mode in cache
|
||||
SET_PERI_REG_BITS(SPI_SRAM_DRD_CMD_REG(0), SPI_CACHE_SRAM_USR_RD_CMD_VALUE_V, ((PSRAM_FAST_READ) << 8),
|
||||
SPI_CACHE_SRAM_USR_RD_CMD_VALUE_S); //0x0b, read command value,(0x00 for delay,0x0b for cmd)
|
||||
SET_PERI_REG_BITS(SPI_SRAM_DWR_CMD_REG(0), SPI_CACHE_SRAM_USR_WR_CMD_BITLEN, 15,
|
||||
SPI_CACHE_SRAM_USR_WR_CMD_BITLEN_S); //write command length,2 bytes(1byte for delay,send in qio mode in cache)
|
||||
SET_PERI_REG_BITS(SPI_SRAM_DWR_CMD_REG(0), SPI_CACHE_SRAM_USR_WR_CMD_VALUE, ((PSRAM_QUAD_WRITE) << 8),
|
||||
SPI_CACHE_SRAM_USR_WR_CMD_VALUE_S); //0x38, write command value,(0x00 for delay)
|
||||
break;
|
||||
}
|
||||
|
||||
DPORT_CLEAR_PERI_REG_MASK(DPORT_PRO_CACHE_CTRL_REG, DPORT_PRO_DRAM_HL|DPORT_PRO_DRAM_SPLIT);
|
||||
DPORT_CLEAR_PERI_REG_MASK(DPORT_APP_CACHE_CTRL_REG, DPORT_APP_DRAM_HL|DPORT_APP_DRAM_SPLIT);
|
||||
if (vaddrmode == PSRAM_VADDR_MODE_LOWHIGH) {
|
||||
DPORT_SET_PERI_REG_MASK(DPORT_PRO_CACHE_CTRL_REG, DPORT_PRO_DRAM_HL);
|
||||
DPORT_SET_PERI_REG_MASK(DPORT_APP_CACHE_CTRL_REG, DPORT_APP_DRAM_HL);
|
||||
} else if (vaddrmode == PSRAM_VADDR_MODE_EVENODD) {
|
||||
DPORT_SET_PERI_REG_MASK(DPORT_PRO_CACHE_CTRL_REG, DPORT_PRO_DRAM_SPLIT);
|
||||
DPORT_SET_PERI_REG_MASK(DPORT_APP_CACHE_CTRL_REG, DPORT_APP_DRAM_SPLIT);
|
||||
}
|
||||
|
||||
DPORT_CLEAR_PERI_REG_MASK(DPORT_PRO_CACHE_CTRL1_REG, DPORT_PRO_CACHE_MASK_DRAM1|DPORT_PRO_CACHE_MASK_OPSDRAM); //use Dram1 to visit ext sram.
|
||||
//cache page mode : 1 -->16k 4 -->2k 0-->32k,(accord with the settings in cache_sram_mmu_set)
|
||||
DPORT_SET_PERI_REG_BITS(DPORT_PRO_CACHE_CTRL1_REG, DPORT_PRO_CMMU_SRAM_PAGE_MODE, 0, DPORT_PRO_CMMU_SRAM_PAGE_MODE_S);
|
||||
DPORT_CLEAR_PERI_REG_MASK(DPORT_APP_CACHE_CTRL1_REG, DPORT_APP_CACHE_MASK_DRAM1|DPORT_APP_CACHE_MASK_OPSDRAM); //use Dram1 to visit ext sram.
|
||||
//cache page mode : 1 -->16k 4 -->2k 0-->32k,(accord with the settings in cache_sram_mmu_set)
|
||||
DPORT_SET_PERI_REG_BITS(DPORT_APP_CACHE_CTRL1_REG, DPORT_APP_CMMU_SRAM_PAGE_MODE, 0, DPORT_APP_CMMU_SRAM_PAGE_MODE_S);
|
||||
|
||||
CLEAR_PERI_REG_MASK(SPI_PIN_REG(0), SPI_CS1_DIS_M); //ENABLE SPI0 CS1 TO PSRAM(CS0--FLASH; CS1--SRAM)
|
||||
|
||||
}
|
||||
|
||||
#endif // CONFIG_SPIRAM_SUPPORT
|
55
components/esp32/spiram_psram.h
Normal file
55
components/esp32/spiram_psram.h
Normal file
@ -0,0 +1,55 @@
|
||||
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
|
||||
#ifndef _PSRAM_H
|
||||
#define _PSRAM_H
|
||||
#include "soc/spi_reg.h"
|
||||
#include "esp_err.h"
|
||||
#include "sdkconfig.h"
|
||||
|
||||
typedef enum {
|
||||
PSRAM_CACHE_F80M_S40M = 0,
|
||||
PSRAM_CACHE_F40M_S40M,
|
||||
PSRAM_CACHE_F80M_S80M,
|
||||
PSRAM_CACHE_MAX,
|
||||
} psram_cache_mode_t;
|
||||
|
||||
|
||||
/*
|
||||
See the TRM, chapter PID/MPU/MMU, header 'External RAM' for the definitions of these modes.
|
||||
|
||||
Important is that NORMAL works with the app CPU cache disabled, but gives huge cache coherency
|
||||
issues when both app and pro CPU are enabled. LOWHIGH and EVENODD do not have these coherency
|
||||
issues but cannot be used when the app CPU cache is disabled.
|
||||
*/
|
||||
typedef enum {
|
||||
PSRAM_VADDR_MODE_NORMAL=0, ///< App and pro CPU use their own flash cache for external RAM access
|
||||
PSRAM_VADDR_MODE_LOWHIGH, ///< App and pro CPU share external RAM caches: pro CPU has low 2M, app CPU has high 2M
|
||||
PSRAM_VADDR_MODE_EVENODD, ///< App and pro CPU share external RAM caches: pro CPU does even 32yte ranges, app does odd ones.
|
||||
} psram_vaddr_mode_t;
|
||||
|
||||
/**
|
||||
* @brief psram cache enable function
|
||||
*
|
||||
* Esp-idf uses this to initialize cache for psram, mapping it into the main memory
|
||||
* address space.
|
||||
*
|
||||
* @param mode SPI mode to access psram in
|
||||
* @param vaddrmode Mode the psram cache works in.
|
||||
* @return ESP_OK on success, ESP_ERR_INVALID_STATE when VSPI peripheral is needed but cannot be claimed.
|
||||
*/
|
||||
esp_err_t psram_enable(psram_cache_mode_t mode, psram_vaddr_mode_t vaddrmode);
|
||||
|
||||
#endif
|
141
components/esp32/test/test_spiram_cache_flush.c
Normal file
141
components/esp32/test/test_spiram_cache_flush.c
Normal file
@ -0,0 +1,141 @@
|
||||
/*
|
||||
This code tests the interaction between PSRAM and SPI flash routines.
|
||||
*/
|
||||
|
||||
#include <esp_types.h>
|
||||
#include <stdio.h>
|
||||
#include "rom/ets_sys.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 "rom/ets_sys.h"
|
||||
#include "esp_heap_caps.h"
|
||||
#include "esp_spi_flash.h"
|
||||
#include "esp_partition.h"
|
||||
#include "test_utils.h"
|
||||
|
||||
|
||||
#if CONFIG_SPIRAM_USE_CAPS_ALLOC || CONFIG_SPIRAM_USE_MEMMAP
|
||||
|
||||
#define TSTSZ (16*1024)
|
||||
|
||||
|
||||
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][ignore]")
|
||||
{
|
||||
void *mem[2];
|
||||
res[0]=0; res[1]=0;
|
||||
#if CONFIG_SPIRAM_USE_CAPS_ALLOC
|
||||
mem[0]=pvPortMallocCaps(TSTSZ, MALLOC_CAP_SPIRAM);
|
||||
mem[1]=pvPortMallocCaps(TSTSZ, MALLOC_CAP_SPIRAM);
|
||||
#else
|
||||
mem[0]=(void*)0x3f800000;
|
||||
mem[1]=(void*)0x3f800000+TSTSZ;
|
||||
#endif
|
||||
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);
|
||||
|
||||
const esp_partition_t* part = get_test_data_partition();
|
||||
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("%d/10\n", l);
|
||||
}
|
||||
|
||||
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 CONFIG_SPIRAM_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][ignore]")
|
||||
{
|
||||
void *mem[2];
|
||||
res[0]=0; res[1]=0;
|
||||
#if CONFIG_SPIRAM_USE_CAPS_ALLOC
|
||||
mem[0]=pvPortMallocCaps(TSTSZ, MALLOC_CAP_SPIRAM);
|
||||
mem[1]=pvPortMallocCaps(TSTSZ, MALLOC_CAP_SPIRAM);
|
||||
#else
|
||||
mem[0]=(void*)0x3f800000;
|
||||
mem[1]=(void*)0x3f800000+TSTSZ;
|
||||
#endif
|
||||
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++) {
|
||||
printf("%d/%d\n", i, CYCLES);
|
||||
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 CONFIG_SPIRAM_USE_CAPS_ALLOC
|
||||
free(mem[0]);
|
||||
free(mem[1]);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif //CONFIG_SPIRAM_USE_CAPS_ALLOC || CONFIG_SPIRAM_USE_MEMMAP
|
@ -1,5 +1,12 @@
|
||||
|
||||
ifdef CONFIG_NEWLIB_NANO_FORMAT
|
||||
|
||||
ifeq ("$(CONFIG_SPIRAM_CACHE_WORKAROUND)","y")
|
||||
LIBC_PATH := $(COMPONENT_PATH)/lib/libc-psram-workaround.a
|
||||
LIBM_PATH := $(COMPONENT_PATH)/lib/libm-psram-workaround.a
|
||||
|
||||
else
|
||||
|
||||
ifeq ("$(CONFIG_NEWLIB_NANO_FORMAT)","y")
|
||||
LIBC_PATH := $(COMPONENT_PATH)/lib/libc_nano.a
|
||||
else
|
||||
LIBC_PATH := $(COMPONENT_PATH)/lib/libc.a
|
||||
@ -7,7 +14,9 @@ endif
|
||||
|
||||
LIBM_PATH := $(COMPONENT_PATH)/lib/libm.a
|
||||
|
||||
COMPONENT_ADD_LDFLAGS += $(LIBC_PATH) $(LIBM_PATH)
|
||||
endif
|
||||
|
||||
COMPONENT_ADD_LDFLAGS := $(LIBC_PATH) $(LIBM_PATH) -lnewlib
|
||||
|
||||
COMPONENT_ADD_LINKER_DEPS := $(LIBC_PATH) $(LIBM_PATH)
|
||||
|
||||
|
BIN
components/newlib/lib/libc-psram-workaround.a
Normal file
BIN
components/newlib/lib/libc-psram-workaround.a
Normal file
Binary file not shown.
BIN
components/newlib/lib/libg-psram-workaround.a
Normal file
BIN
components/newlib/lib/libg-psram-workaround.a
Normal file
Binary file not shown.
BIN
components/newlib/lib/libm-psram-workaround.a
Normal file
BIN
components/newlib/lib/libm-psram-workaround.a
Normal file
Binary file not shown.
0
components/soc/component.mk
Executable file → Normal file
0
components/soc/component.mk
Executable file → Normal file
@ -67,6 +67,9 @@
|
||||
#define SOC_RTC_IRAM_HIGH 0x400C2000
|
||||
#define SOC_RTC_DATA_LOW 0x50000000
|
||||
#define SOC_RTC_DATA_HIGH 0x50002000
|
||||
#define SOC_EXTRAM_DATA_LOW 0x3F800000
|
||||
#define SOC_EXTRAM_DATA_HIGH 0x3FC00000
|
||||
|
||||
|
||||
#define DR_REG_DPORT_BASE 0x3ff00000
|
||||
#define DR_REG_AES_BASE 0x3ff01000
|
||||
|
@ -31,6 +31,7 @@
|
||||
#include "esp_flash_encrypt.h"
|
||||
#include "esp_log.h"
|
||||
#include "cache_utils.h"
|
||||
#include "esp_spiram.h"
|
||||
|
||||
#ifndef NDEBUG
|
||||
// Enable built-in checks in queue.h in debug builds
|
||||
@ -225,6 +226,9 @@ esp_err_t IRAM_ATTR spi_flash_mmap_pages(int *pages, size_t page_count, spi_flas
|
||||
entire cache.
|
||||
*/
|
||||
if (!did_flush && need_flush) {
|
||||
#if CONFIG_SPIRAM_SUPPORT
|
||||
esp_spiram_writeback_cache();
|
||||
#endif
|
||||
Cache_Flush(0);
|
||||
Cache_Flush(1);
|
||||
}
|
||||
@ -330,6 +334,9 @@ static inline IRAM_ATTR bool update_written_pages(size_t start_addr, size_t leng
|
||||
tricky because mmaped memory can be used on un-pinned
|
||||
cores, or the pointer passed between CPUs.
|
||||
*/
|
||||
#if CONFIG_SPIRAM_SUPPORT
|
||||
esp_spiram_writeback_cache();
|
||||
#endif
|
||||
Cache_Flush(0);
|
||||
#ifndef CONFIG_FREERTOS_UNICORE
|
||||
Cache_Flush(1);
|
||||
|
@ -118,6 +118,7 @@ CONFIG_BT_RESERVE_DRAM=0
|
||||
CONFIG_ESP32_DEFAULT_CPU_FREQ_240=y
|
||||
CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ=240
|
||||
CONFIG_MEMMAP_SMP=y
|
||||
# CONFIG_SPIRAM_SUPPORT is not set
|
||||
# CONFIG_MEMMAP_TRACEMEM is not set
|
||||
# CONFIG_MEMMAP_TRACEMEM_TWOBANKS is not set
|
||||
# CONFIG_ESP32_TRAX is not set
|
||||
|
Loading…
x
Reference in New Issue
Block a user