Merge branch 'feat/psram_support_hspi' into 'master'
esp32: support to use hspi to output clock for 4M psram See merge request idf/esp-idf!3377
This commit is contained in:
commit
621e316725
|
@ -1336,7 +1336,7 @@ UT_004_13:
|
||||||
- ESP32_IDF
|
- ESP32_IDF
|
||||||
- UT_T1_1
|
- UT_T1_1
|
||||||
- psram
|
- psram
|
||||||
|
|
||||||
UT_005_01:
|
UT_005_01:
|
||||||
<<: *unit_test_template
|
<<: *unit_test_template
|
||||||
tags:
|
tags:
|
||||||
|
@ -1522,6 +1522,20 @@ UT_012_03:
|
||||||
- UT_T1_1
|
- UT_T1_1
|
||||||
- 8Mpsram
|
- 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:
|
UT_601_01:
|
||||||
<<: *unit_test_template
|
<<: *unit_test_template
|
||||||
tags:
|
tags:
|
||||||
|
|
|
@ -96,9 +96,32 @@ typedef struct {
|
||||||
* Call this if your driver wants to manage a SPI peripheral.
|
* Call this if your driver wants to manage a SPI peripheral.
|
||||||
*
|
*
|
||||||
* @param host Peripheral to claim
|
* @param host Peripheral to claim
|
||||||
|
* @param source The caller indentification string.
|
||||||
|
*
|
||||||
* @return True if peripheral is claimed successfully; false if peripheral already is claimed.
|
* @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.
|
* @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);
|
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.
|
* @brief Return the SPI DMA channel so other driver can claim it, or just to power down DMA.
|
||||||
*
|
*
|
||||||
|
|
|
@ -52,19 +52,30 @@ typedef struct spi_device_t spi_device_t;
|
||||||
|
|
||||||
//Periph 1 is 'claimed' by SPI flash code.
|
//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 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 uint8_t spi_dma_chan_enabled = 0;
|
||||||
static portMUX_TYPE spi_dma_spinlock = portMUX_INITIALIZER_UNLOCKED;
|
static portMUX_TYPE spi_dma_spinlock = portMUX_INITIALIZER_UNLOCKED;
|
||||||
|
|
||||||
|
|
||||||
//Returns true if this peripheral is successfully claimed, false if otherwise.
|
//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 false_var = false;
|
||||||
bool ret = atomic_compare_exchange_strong(&spi_periph_claimed[host], &false_var, true);
|
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;
|
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.
|
//Returns true if this peripheral is successfully freed, false if otherwise.
|
||||||
bool spicommon_periph_free(spi_host_device_t host)
|
bool spicommon_periph_free(spi_host_device_t host)
|
||||||
{
|
{
|
||||||
|
@ -102,6 +113,12 @@ bool spicommon_dma_chan_claim (int dma_chan)
|
||||||
return ret;
|
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)
|
bool spicommon_dma_chan_free(int dma_chan)
|
||||||
{
|
{
|
||||||
assert( dma_chan == 1 || dma_chan == 2 );
|
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) {
|
if (use_iomux) {
|
||||||
//All SPI iomux pin selections resolve to 1, so we put that here instead of trying to figure
|
//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.
|
//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) {
|
if (bus_config->mosi_io_num >= 0) {
|
||||||
gpio_iomux_in(bus_config->mosi_io_num, spi_periph_signal[host].spid_in);
|
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);
|
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;
|
temp_flag |= SPICOMMON_BUSFLAG_NATIVE_PINS;
|
||||||
} else {
|
} else {
|
||||||
//Use GPIO matrix
|
//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 (bus_config->mosi_io_num >= 0) {
|
||||||
if (mosi_output || (temp_flag&SPICOMMON_BUSFLAG_DUAL)) {
|
if (mosi_output || (temp_flag&SPICOMMON_BUSFLAG_DUAL)) {
|
||||||
gpio_set_direction(bus_config->mosi_io_num, GPIO_MODE_INPUT_OUTPUT);
|
gpio_set_direction(bus_config->mosi_io_num, GPIO_MODE_INPUT_OUTPUT);
|
||||||
|
|
|
@ -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(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_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);
|
SPI_CHECK(spi_chan_claimed, "host already in use", ESP_ERR_INVALID_STATE);
|
||||||
|
|
||||||
if ( dma_chan != 0 ) {
|
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_mode = 0;
|
||||||
spihost[host]->hw->ctrl2.mosi_delay_num = 0;
|
spihost[host]->hw->ctrl2.mosi_delay_num = 0;
|
||||||
*handle=dev;
|
*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;
|
return ESP_OK;
|
||||||
|
|
||||||
nomem:
|
nomem:
|
||||||
|
|
|
@ -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(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_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);
|
SPI_CHECK(spi_chan_claimed, "host already in use", ESP_ERR_INVALID_STATE);
|
||||||
|
|
||||||
if ( dma_chan != 0 ) {
|
if ( dma_chan != 0 ) {
|
||||||
|
|
|
@ -24,7 +24,7 @@ config SPIRAM_SUPPORT
|
||||||
bool "Support for external, SPI-connected RAM"
|
bool "Support for external, SPI-connected RAM"
|
||||||
default "n"
|
default "n"
|
||||||
help
|
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.
|
main SPI flash chip.
|
||||||
|
|
||||||
menu "SPI RAM config"
|
menu "SPI RAM config"
|
||||||
|
@ -98,9 +98,10 @@ choice SPIRAM_SPEED
|
||||||
2. Flash SPI running at 80Mhz 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
|
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.
|
Note: If the third mode(80Mhz+80Mhz) is enabled for SPI RAM of type 32MBit, one of the HSPI/VSPI host will
|
||||||
Application code should never touch VSPI hardware in this case. The option to select
|
be occupied by the system. Which SPI host to use can be selected by the config item SPIRAM_OCCUPY_SPI_HOST.
|
||||||
80MHz will only be visible if the flash SPI speed is also 80MHz. (ESPTOOLPY_FLASHFREQ_80M is true)
|
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
|
config SPIRAM_SPEED_40M
|
||||||
bool "40MHz clock speed"
|
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
|
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
|
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.
|
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
|
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.
|
with the workaround and located in flash instead.
|
||||||
|
|
||||||
|
@ -146,9 +147,9 @@ config SPIRAM_BANKSWITCH_RESERVE
|
||||||
default 8
|
default 8
|
||||||
range 1 62
|
range 1 62
|
||||||
help
|
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.
|
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
|
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
|
any himem calls, the reservation is not done and the original amount of memory will be available
|
||||||
to malloc/esp_heap_alloc_caps.
|
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.
|
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
|
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.
|
region instead, so malloc() will not suddenly fail when either internal or external memory is full.
|
||||||
|
|
||||||
config WIFI_LWIP_ALLOCATION_FROM_SPIRAM_FIRST
|
config WIFI_LWIP_ALLOCATION_FROM_SPIRAM_FIRST
|
||||||
bool "Try to allocate memories of WiFi and LWIP in SPIRAM firstly. If failed, allocate internal memory"
|
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
|
depends on SPIRAM_USE_CAPS_ALLOC || SPIRAM_USE_MALLOC
|
||||||
|
@ -179,12 +180,12 @@ config SPIRAM_MALLOC_RESERVE_INTERNAL
|
||||||
help
|
help
|
||||||
Because the external/internal RAM allocation strategy is not always perfect, it sometimes may happen
|
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
|
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
|
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
|
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.
|
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.
|
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;
|
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.
|
be sure to keep this in mind when adjusting this value.
|
||||||
|
|
||||||
|
@ -211,7 +212,21 @@ config SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY
|
||||||
help
|
help
|
||||||
If enabled the option,and add EXT_RAM_ATTR defined your variable,then your variable will be placed
|
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
|
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
|
endmenu
|
||||||
|
|
||||||
|
@ -257,8 +272,8 @@ choice ESP32_COREDUMP_TO_FLASH_OR_UART
|
||||||
help
|
help
|
||||||
Select place to store core dump: flash, uart or none (to disable core dumps generation).
|
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
|
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
|
corresponding entry to your CSV. For examples, please see predefined partition table CSV descriptions
|
||||||
in the components/partition_table directory.
|
in the components/partition_table directory.
|
||||||
|
|
||||||
config ESP32_ENABLE_COREDUMP_TO_FLASH
|
config ESP32_ENABLE_COREDUMP_TO_FLASH
|
||||||
|
@ -297,18 +312,18 @@ choice NUMBER_OF_UNIVERSAL_MAC_ADDRESS
|
||||||
default FOUR_UNIVERSAL_MAC_ADDRESS
|
default FOUR_UNIVERSAL_MAC_ADDRESS
|
||||||
help
|
help
|
||||||
Configure the number of universally administered (by IEEE) MAC addresses.
|
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.
|
single base MAC address.
|
||||||
If the number of universal MAC addresses is four, all four interfaces (WiFi station, WiFi softap,
|
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
|
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.
|
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)
|
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
|
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)
|
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
|
receive local MAC addresses. These are derived from the universal WiFi station and Bluetooth MAC
|
||||||
addresses, respectively.
|
addresses, respectively.
|
||||||
When using the default (Espressif-assigned) base MAC address, either setting can be used. When using
|
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
|
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.)
|
addresses in this range (either 2 or 4 per device.)
|
||||||
|
|
||||||
config TWO_UNIVERSAL_MAC_ADDRESS
|
config TWO_UNIVERSAL_MAC_ADDRESS
|
||||||
|
@ -318,7 +333,7 @@ config FOUR_UNIVERSAL_MAC_ADDRESS
|
||||||
endchoice
|
endchoice
|
||||||
|
|
||||||
config NUMBER_OF_UNIVERSAL_MAC_ADDRESS
|
config NUMBER_OF_UNIVERSAL_MAC_ADDRESS
|
||||||
int
|
int
|
||||||
default 2 if TWO_UNIVERSAL_MAC_ADDRESS
|
default 2 if TWO_UNIVERSAL_MAC_ADDRESS
|
||||||
default 4 if FOUR_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
|
to dispatch callbacks of timers created using ets_timer and esp_timer
|
||||||
APIs. If you are seing stack overflow errors in timer task, increase
|
APIs. If you are seing stack overflow errors in timer task, increase
|
||||||
this value.
|
this value.
|
||||||
|
|
||||||
Note that this is not the same as FreeRTOS timer task. To configure
|
Note that this is not the same as FreeRTOS timer task. To configure
|
||||||
FreeRTOS timer task size, see "FreeRTOS timer task stack size" option
|
FreeRTOS timer task size, see "FreeRTOS timer task stack size" option
|
||||||
in "FreeRTOS" menu.
|
in "FreeRTOS" menu.
|
||||||
|
|
||||||
choice NEWLIB_STDOUT_LINE_ENDING
|
choice NEWLIB_STDOUT_LINE_ENDING
|
||||||
prompt "Line ending for UART output"
|
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
|
This option allows configuring the desired line endings sent to UART
|
||||||
when a newline ('\n', LF) appears on stdout.
|
when a newline ('\n', LF) appears on stdout.
|
||||||
Three options are possible:
|
Three options are possible:
|
||||||
|
|
||||||
CRLF: whenever LF is encountered, prepend it with CR
|
CRLF: whenever LF is encountered, prepend it with CR
|
||||||
|
|
||||||
LF: no modification is applied, stdout is sent as is
|
LF: no modification is applied, stdout is sent as is
|
||||||
|
|
||||||
CR: each occurence of LF is replaced with CR
|
CR: each occurence of LF is replaced with CR
|
||||||
|
|
||||||
This option doesn't affect behavior of the UART driver (drivers/uart.h).
|
This option doesn't affect behavior of the UART driver (drivers/uart.h).
|
||||||
|
|
||||||
config NEWLIB_STDOUT_LINE_ENDING_CRLF
|
config NEWLIB_STDOUT_LINE_ENDING_CRLF
|
||||||
bool "CRLF"
|
bool "CRLF"
|
||||||
config NEWLIB_STDOUT_LINE_ENDING_LF
|
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
|
This option allows configuring which input sequence on UART produces
|
||||||
a newline ('\n', LF) on stdin.
|
a newline ('\n', LF) on stdin.
|
||||||
Three options are possible:
|
Three options are possible:
|
||||||
|
|
||||||
CRLF: CRLF is converted to LF
|
CRLF: CRLF is converted to LF
|
||||||
|
|
||||||
LF: no modification is applied, input is sent to stdin as is
|
LF: no modification is applied, input is sent to stdin as is
|
||||||
|
|
||||||
CR: each occurence of CR is replaced with LF
|
CR: each occurence of CR is replaced with LF
|
||||||
|
|
||||||
This option doesn't affect behavior of the UART driver (drivers/uart.h).
|
This option doesn't affect behavior of the UART driver (drivers/uart.h).
|
||||||
|
|
||||||
config NEWLIB_STDIN_LINE_ENDING_CRLF
|
config NEWLIB_STDIN_LINE_ENDING_CRLF
|
||||||
bool "CRLF"
|
bool "CRLF"
|
||||||
config NEWLIB_STDIN_LINE_ENDING_LF
|
config NEWLIB_STDIN_LINE_ENDING_LF
|
||||||
|
@ -445,7 +460,7 @@ choice CONSOLE_UART
|
||||||
default CONSOLE_UART_DEFAULT
|
default CONSOLE_UART_DEFAULT
|
||||||
help
|
help
|
||||||
Select whether to use UART for console output (through stdout and stderr).
|
Select whether to use UART for console output (through stdout and stderr).
|
||||||
|
|
||||||
- Default is to use UART0 on pins GPIO1(TX) and GPIO3(RX).
|
- Default is to use UART0 on pins GPIO1(TX) and GPIO3(RX).
|
||||||
- If "Custom" is selected, UART0 or UART1 can be chosen,
|
- If "Custom" is selected, UART0 or UART1 can be chosen,
|
||||||
and any pins can be selected.
|
and any pins can be selected.
|
||||||
|
@ -559,10 +574,10 @@ config ESP32_DEBUG_OCDAWARE
|
||||||
|
|
||||||
config ESP32_DEBUG_STUBS_ENABLE
|
config ESP32_DEBUG_STUBS_ENABLE
|
||||||
bool "OpenOCD debug stubs"
|
bool "OpenOCD debug stubs"
|
||||||
default OPTIMIZATION_LEVEL_DEBUG
|
default OPTIMIZATION_LEVEL_DEBUG
|
||||||
depends on !ESP32_TRAX
|
depends on !ESP32_TRAX
|
||||||
help
|
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.
|
e.g. GCOV data dump.
|
||||||
|
|
||||||
config INT_WDT
|
config INT_WDT
|
||||||
|
@ -596,7 +611,7 @@ config TASK_WDT
|
||||||
help
|
help
|
||||||
The Task Watchdog Timer can be used to make sure individual tasks are still
|
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
|
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)
|
initialized after startup as well (see Task Watchdog Timer API Reference)
|
||||||
|
|
||||||
config TASK_WDT_PANIC
|
config TASK_WDT_PANIC
|
||||||
|
@ -710,7 +725,7 @@ choice ESP32_TIME_SYSCALL
|
||||||
continue in deep sleep. Time will be reported at 1 microsecond
|
continue in deep sleep. Time will be reported at 1 microsecond
|
||||||
resolution. This is the default, and the recommended option.
|
resolution. This is the default, and the recommended option.
|
||||||
- If only high-resolution timer is used, gettimeofday will
|
- 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.
|
Time will not be preserved when going into deep sleep mode.
|
||||||
- If only RTC timer is used, timekeeping will continue in
|
- If only RTC timer is used, timekeeping will continue in
|
||||||
deep sleep, but time will be measured at 6.(6) microsecond
|
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
|
default ESP32_RTC_CLOCK_SOURCE_INTERNAL_RC
|
||||||
help
|
help
|
||||||
Choose which clock is used as RTC clock source.
|
Choose which clock is used as RTC clock source.
|
||||||
|
|
||||||
- "Internal 150kHz oscillator" option provides lowest deep sleep current
|
- "Internal 150kHz oscillator" option provides lowest deep sleep current
|
||||||
consumption, and does not require extra external components. However
|
consumption, and does not require extra external components. However
|
||||||
frequency stability with respect to temperature is poor, so time may
|
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.
|
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
|
- "Internal 8.5MHz oscillator divided by 256" option results in higher
|
||||||
deep sleep current (by 5uA) but has better frequency stability than
|
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
|
config ESP32_RTC_CLOCK_SOURCE_INTERNAL_RC
|
||||||
bool "Internal 150kHz RC oscillator"
|
bool "Internal 150kHz RC oscillator"
|
||||||
|
@ -777,7 +792,7 @@ config ESP32_RTC_CLK_CAL_CYCLES
|
||||||
by the calibration routine. Higher numbers increase calibration
|
by the calibration routine. Higher numbers increase calibration
|
||||||
precision, which may be important for applications which spend a lot of
|
precision, which may be important for applications which spend a lot of
|
||||||
time in deep sleep. Lower numbers reduce startup time.
|
time in deep sleep. Lower numbers reduce startup time.
|
||||||
|
|
||||||
When this option is set to 0, clock calibration will not be performed at
|
When this option is set to 0, clock calibration will not be performed at
|
||||||
startup, and approximate clock frequencies will be assumed:
|
startup, and approximate clock frequencies will be assumed:
|
||||||
|
|
||||||
|
@ -792,15 +807,15 @@ config ESP32_RTC_XTAL_BOOTSTRAP_CYCLES
|
||||||
default 5
|
default 5
|
||||||
range 0 32768
|
range 0 32768
|
||||||
help
|
help
|
||||||
To reduce the startup time of an external RTC crystal,
|
To reduce the startup time of an external RTC crystal,
|
||||||
we bootstrap it with a 32kHz square wave for a fixed number of cycles.
|
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
|
Setting 0 will disable bootstrapping (if disabled, the crystal may take
|
||||||
longer to start up or fail to oscillate under some conditions).
|
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.
|
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).
|
set a larger "Number of cycles for RTC_SLOW_CLK calibration" (about 3000).
|
||||||
|
|
||||||
config ESP32_DEEP_SLEEP_WAKEUP_DELAY
|
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,
|
time to pass between power on and first read operation. By default,
|
||||||
without any extra delay, this time is approximately 900us, although
|
without any extra delay, this time is approximately 900us, although
|
||||||
some flash chip types need more than that.
|
some flash chip types need more than that.
|
||||||
|
|
||||||
By default extra delay is set to 2000us. When optimizing startup time
|
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
|
If you are seeing "flash read err, 1000" message printed to the
|
||||||
console after deep sleep reset, try increasing this value.
|
console after deep sleep reset, try increasing this value.
|
||||||
|
@ -915,7 +930,7 @@ config ESP32_RTCDATA_IN_FAST_MEM
|
||||||
help
|
help
|
||||||
This option allows to place .rtc_data and .rtc_rodata sections into
|
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.
|
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.
|
can be accessed only by PRO_CPU core.
|
||||||
|
|
||||||
endmenu # ESP32-Specific
|
endmenu # ESP32-Specific
|
||||||
|
@ -1052,8 +1067,8 @@ config ESP32_WIFI_CSI_ENABLED
|
||||||
bool "WiFi CSI(Channel State Information)"
|
bool "WiFi CSI(Channel State Information)"
|
||||||
default n
|
default n
|
||||||
help
|
help
|
||||||
Select this option to enable CSI(Channel State Information) feature. CSI takes about
|
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
|
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.
|
this feature in order to save memory.
|
||||||
|
|
||||||
config ESP32_WIFI_AMPDU_TX_ENABLED
|
config ESP32_WIFI_AMPDU_TX_ENABLED
|
||||||
|
@ -1070,7 +1085,7 @@ config ESP32_WIFI_TX_BA_WIN
|
||||||
default 6
|
default 6
|
||||||
help
|
help
|
||||||
Set the size of WiFi Block Ack TX window. Generally a bigger value means higher throughput but
|
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
|
test the maximum UDP TX throughput with iperf etc. For iperf test in shieldbox, the recommended
|
||||||
value is 9~12.
|
value is 9~12.
|
||||||
|
|
||||||
|
@ -1086,8 +1101,8 @@ config ESP32_WIFI_RX_BA_WIN
|
||||||
range 2 32
|
range 2 32
|
||||||
default 6
|
default 6
|
||||||
help
|
help
|
||||||
Set the size of WiFi Block Ack RX window. Generally a bigger value means higher throughput but
|
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.
|
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
|
test the maximum UDP RX throughput with iperf etc. For iperf test in shieldbox, the recommended
|
||||||
value is 9~12.
|
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
|
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
|
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
|
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
|
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.
|
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.
|
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
|
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).
|
932 (752+36*5).
|
||||||
|
|
||||||
Setting a longer beacon length also assists with debugging as the conflicting root nodes can be identified more quickly.
|
Setting a longer beacon length also assists with debugging as the conflicting root nodes can be identified more quickly.
|
||||||
|
|
||||||
endmenu # Wi-Fi
|
endmenu # Wi-Fi
|
||||||
|
|
||||||
menu PHY
|
menu PHY
|
||||||
|
@ -1139,7 +1154,7 @@ config ESP32_PHY_CALIBRATION_AND_DATA_STORAGE
|
||||||
help
|
help
|
||||||
If this option is enabled, NVS will be initialized and calibration data will be loaded from there.
|
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
|
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 this option is disabled, full calibration will be performed.
|
||||||
|
|
||||||
If it's easy that your board calibrate bad data, choose 'n'.
|
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.
|
into the application binary.
|
||||||
|
|
||||||
If unsure, choose 'n'.
|
If unsure, choose 'n'.
|
||||||
|
|
||||||
config ESP32_PHY_MAX_WIFI_TX_POWER
|
config ESP32_PHY_MAX_WIFI_TX_POWER
|
||||||
int "Max WiFi TX power (dBm)"
|
int "Max WiFi TX power (dBm)"
|
||||||
range 0 20
|
range 0 20
|
||||||
|
@ -1189,7 +1204,7 @@ config PM_ENABLE
|
||||||
This option has run-time overhead (increased interrupt latency,
|
This option has run-time overhead (increased interrupt latency,
|
||||||
longer time to enter idle state), and it also reduces accuracy of
|
longer time to enter idle state), and it also reduces accuracy of
|
||||||
RTOS ticks and timers used for timekeeping.
|
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
|
config PM_DFS_INIT_AUTO
|
||||||
bool "Enable dynamic frequency scaling (DFS) at startup"
|
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
|
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
|
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
|
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
|
config PM_TRACE
|
||||||
bool "Enable debug tracing of PM using GPIOs"
|
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
|
This feature is intended to be used when analyzing/debugging behavior
|
||||||
of power management implementation, and should be kept disabled in
|
of power management implementation, and should be kept disabled in
|
||||||
applications.
|
applications.
|
||||||
|
|
||||||
|
|
||||||
endmenu # "Power Management"
|
endmenu # "Power Management"
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
#include "driver/periph_ctrl.h"
|
#include "driver/periph_ctrl.h"
|
||||||
#include "xtensa/core-macros.h"
|
#include "xtensa/core-macros.h"
|
||||||
#include "bootloader_clock.h"
|
#include "bootloader_clock.h"
|
||||||
|
#include "driver/spi_common.h"
|
||||||
|
|
||||||
/* Number of cycles to wait from the 32k XTAL oscillator to consider it running.
|
/* 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
|
* 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
|
// Wait for UART TX to finish, otherwise some UART output will be lost
|
||||||
// when switching APB frequency
|
// when switching APB frequency
|
||||||
uart_tx_wait_idle(CONFIG_CONSOLE_UART_NUM);
|
uart_tx_wait_idle(CONFIG_CONSOLE_UART_NUM);
|
||||||
|
|
||||||
rtc_clk_cpu_freq_set_config(&new_config);
|
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 );
|
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;
|
DPORT_SPI_DMA_CLK_EN;
|
||||||
|
|
||||||
#if CONFIG_SPIRAM_SPEED_80M
|
#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'
|
//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
|
//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.
|
//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
|
#endif
|
||||||
|
|
||||||
/* Change I2S clock to audio PLL first. Because if I2S uses 160MHz clock,
|
/* Change I2S clock to audio PLL first. Because if I2S uses 160MHz clock,
|
||||||
|
|
|
@ -98,6 +98,27 @@ typedef enum {
|
||||||
#define _SPI_80M_CLK_DIV 1
|
#define _SPI_80M_CLK_DIV 1
|
||||||
#define _SPI_40M_CLK_DIV 2
|
#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";
|
static const char* TAG = "psram";
|
||||||
typedef enum {
|
typedef enum {
|
||||||
PSRAM_SPI_1 = 0x1,
|
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);
|
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_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 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
|
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
|
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:
|
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)
|
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);
|
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)) {
|
} else if (PSRAM_IS_32MBIT_VER0(s_psram_id)) {
|
||||||
s_clk_mode = PSRAM_CLK_MODE_DCLK;
|
s_clk_mode = PSRAM_CLK_MODE_DCLK;
|
||||||
if (mode == PSRAM_CACHE_F80M_S80M) {
|
if (mode == PSRAM_CACHE_F80M_S80M) {
|
||||||
/* note: If the third mode(80Mhz+80Mhz) is enabled for 32MBit 1V8 psram, VSPI port will be
|
/* note: If the third mode(80Mhz+80Mhz) is enabled for 32MBit 1V8 psram, one of HSPI/VSPI port will be
|
||||||
occupied by the system.
|
occupied by the system (according to kconfig).
|
||||||
Application code should never touch VSPI hardware in this case. We try to stop applications
|
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 */
|
from doing this using the drivers by claiming the port for ourselves */
|
||||||
periph_module_enable(PERIPH_VSPI_MODULE);
|
periph_module_enable(PSRAM_SPI_MODULE);
|
||||||
bool r=spicommon_periph_claim(VSPI_HOST);
|
bool r=spicommon_periph_claim(PSRAM_SPI_HOST, "psram");
|
||||||
if (!r) {
|
if (!r) {
|
||||||
return ESP_ERR_INVALID_STATE;
|
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
|
//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
|
//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.
|
//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_ADDR_REG(PSRAM_SPI_NUM), 32 << 24);
|
||||||
WRITE_PERI_REG(SPI_CLOCK_REG(PSRAM_SPI_3), SPI_CLK_EQU_SYSCLK_M); //SET 80M AND CLEAR OTHERS
|
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_3), SPI_FLASH_READ_M);
|
SET_PERI_REG_MASK(SPI_CMD_REG(PSRAM_SPI_NUM), SPI_FLASH_READ_M);
|
||||||
uint32_t spi_status;
|
uint32_t spi_status;
|
||||||
while (1) {
|
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) {
|
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;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,30 +1,38 @@
|
||||||
set(COMPONENT_SRCDIRS ".")
|
if (CONFIG_TEST_ESP32_SUBTEST_ONLY)
|
||||||
set(COMPONENT_ADD_INCLUDEDIRS ". ${CMAKE_CURRENT_BINARY_DIR}")
|
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"
|
set(COMPONENT_REQUIRES unity nvs_flash ulp)
|
||||||
COMMAND xxd -i "logo.jpg" "${CMAKE_CURRENT_BINARY_DIR}/test_tjpgd_logo.h"
|
|
||||||
WORKING_DIRECTORY ${COMPONENT_PATH}
|
|
||||||
DEPENDS "${CMAKE_CURRENT_LIST_DIR}/logo.jpg")
|
|
||||||
|
|
||||||
# Calculate MD5 value of header file esp_wifi_os_adapter.h
|
register_component()
|
||||||
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)
|
|
||||||
|
|
||||||
# Calculate MD5 value of header file esp_wifi_crypto_types.h
|
add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/test_tjpgd_logo.h"
|
||||||
execute_process(COMMAND md5sum ${IDF_PATH}/components/esp32/include/esp_wifi_crypto_types.h
|
COMMAND xxd -i "logo.jpg" "${CMAKE_CURRENT_BINARY_DIR}/test_tjpgd_logo.h"
|
||||||
COMMAND cut -c 1-7
|
WORKING_DIRECTORY ${COMPONENT_PATH}
|
||||||
OUTPUT_VARIABLE WIFI_CRYPTO_MD5
|
DEPENDS "${CMAKE_CURRENT_LIST_DIR}/logo.jpg")
|
||||||
OUTPUT_STRIP_TRAILING_WHITESPACE)
|
|
||||||
|
|
||||||
add_definitions(-DWIFI_OS_ADAPTER_MD5=\"${WIFI_OS_ADAPTER_MD5}\")
|
# Calculate MD5 value of header file esp_wifi_os_adapter.h
|
||||||
add_definitions(-DWIFI_CRYPTO_MD5=\"${WIFI_CRYPTO_MD5}\")
|
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)
|
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()
|
|
@ -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_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
|
# 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)\"
|
WIFI_OS_ADAPTER_MD5_VAL=\"$(shell md5sum $(IDF_PATH)/components/esp32/include/esp_wifi_os_adapter.h | cut -c 1-7)\"
|
||||||
|
|
69
components/esp32/test/psram_4m/test_4mpsram.c
Normal file
69
components/esp32/test/psram_4m/test_4mpsram.c
Normal file
|
@ -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
|
||||||
|
}
|
|
@ -7,8 +7,8 @@ Support for external RAM
|
||||||
Introduction
|
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,
|
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
|
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.
|
in the memory map and is, within certain restrictions, usable in the same way internal data RAM is.
|
||||||
|
|
||||||
Hardware
|
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
|
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.
|
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
|
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.
|
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
|
* 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``.
|
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
|
* 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
|
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
|
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.
|
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
|
* 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
|
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.)
|
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
|
* 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
|
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
|
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.
|
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
|
* 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
|
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
|
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.
|
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
|
* 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:
|
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.
|
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
|
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
|
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
|
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:
|
ECO_ document. In particular, ESP-IDF handles the bugs mentioned in the following ways:
|
||||||
|
|
||||||
ESP32 rev v0
|
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
|
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).
|
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
|
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.
|
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
|
In ESP-IDF, this flag is enabled when you select :ref:`CONFIG_SPIRAM_CACHE_WORKAROUND`. ESP-IDF also takes other measures to make
|
||||||
|
|
|
@ -13,3 +13,14 @@ config UNITY_FREERTOS_STACK_SIZE
|
||||||
default 8192
|
default 8192
|
||||||
|
|
||||||
endmenu
|
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
|
||||||
|
|
6
tools/unit-test-app/configs/psram_hspi
Normal file
6
tools/unit-test-app/configs/psram_hspi
Normal file
|
@ -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
|
6
tools/unit-test-app/configs/psram_vspi
Normal file
6
tools/unit-test-app/configs/psram_vspi
Normal file
|
@ -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
|
Loading…
Reference in a new issue