Add support to PSRAM using SPIRAM interface
This commit is contained in:
parent
d1225f3110
commit
232aa62f03
@ -15,6 +15,8 @@ config ARCH_CHIP_ESP32
|
||||
select XTENSA_HAVE_INTERRUPTS
|
||||
select ARCH_HAVE_MULTICPU
|
||||
select ARCH_HAVE_MODULE_TEXT
|
||||
select ARCH_HAVE_SDRAM
|
||||
select ARCH_HAVE_HEAP2
|
||||
select ARCH_HAVE_RESET
|
||||
select ARCH_TOOLCHAIN_GNU
|
||||
---help---
|
||||
|
@ -131,6 +131,26 @@ config ESP32_SPI3
|
||||
select ESP32_GPIO_IRQ
|
||||
select SPI
|
||||
|
||||
config ESP32_SPIRAM
|
||||
bool "SPI RAM Support"
|
||||
default n
|
||||
|
||||
if ESP32_SPIRAM && SMP
|
||||
|
||||
choice
|
||||
prompt "How does SPIRAM share cache?"
|
||||
default ESP32_MEMMAP_SPIRAM_CACHE_EVENODD
|
||||
help
|
||||
Selects the cache mode to CPU access the external memory.
|
||||
|
||||
config ESP32_MEMMAP_SPIRAM_CACHE_EVENODD
|
||||
bool "Pro CPU uses even 32 byte ranges, App uses odd ones"
|
||||
config ESP32_MEMMAP_SPIRAM_CACHE_LOWHIGH
|
||||
bool "Pro CPU uses low 2MB ranges, App uses high ones"
|
||||
endchoice # CPU frequency
|
||||
|
||||
endif
|
||||
|
||||
config XTENSA_TIMER1
|
||||
bool "Xtensa Timer 1"
|
||||
default n
|
||||
@ -497,6 +517,78 @@ config ESP32_SPIFLASH_DEBUG
|
||||
|
||||
endmenu # ESP32_SPIFLASH
|
||||
|
||||
menu "SPI RAM Config"
|
||||
depends on ESP32_SPIRAM
|
||||
|
||||
choice ESP32_SPIRAM_TYPE
|
||||
prompt "Type of SPI RAM chip in use"
|
||||
default ESP32_SPIRAM_TYPE_AUTO
|
||||
|
||||
config ESP32_SPIRAM_TYPE_AUTO
|
||||
bool "Auto-detect"
|
||||
|
||||
config ESP32_SPIRAM_TYPE_ESPPSRAM32
|
||||
bool "ESP-PSRAM32 or IS25WP032"
|
||||
|
||||
config ESP32_SPIRAM_TYPE_ESPPSRAM64
|
||||
bool "ESP-PSRAM64 or LY68L6400"
|
||||
endchoice #ESP32_SPIRAM_TYPE
|
||||
|
||||
config ESP32_SPIRAM_SIZE
|
||||
int
|
||||
default -1 if ESP32_SPIRAM_TYPE_AUTO
|
||||
default 4194304 if ESP32_SPIRAM_TYPE_ESPPSRAM32
|
||||
default 8388608 if ESP32_SPIRAM_TYPE_ESPPSRAM64
|
||||
default 0
|
||||
|
||||
choice ESP32_SPIRAM_SPEED
|
||||
prompt "Set RAM clock speed"
|
||||
default ESP32_SPIRAM_SPEED_40M
|
||||
help
|
||||
Select the speed for the SPI RAM chip.
|
||||
|
||||
config ESP32_SPIRAM_SPEED_40M
|
||||
bool "40MHz clock speed"
|
||||
|
||||
config ESP32_SPIRAM_SPEED_80M
|
||||
bool "80MHz clock speed"
|
||||
|
||||
endchoice # ESP32_SPIRAM_SPEED
|
||||
|
||||
config ESP32_SPIRAM_BOOT_INIT
|
||||
bool "Initialize SPI RAM during startup"
|
||||
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.
|
||||
|
||||
config ESP32_SPIRAM_IGNORE_NOTFOUND
|
||||
bool "Ignore PSRAM when not found"
|
||||
default "n"
|
||||
depends on ESP_SPIRAM_BOOT_INIT && !BOOT_SDRAM_DATA
|
||||
help
|
||||
Normally, if psram initialization is enabled during compile time
|
||||
but not found at runtime, it is seen as an error making the CPU
|
||||
panic. If this is enabled, booting will complete but no PSRAM
|
||||
will be available.
|
||||
|
||||
config ESP32_SPIRAM_2T_MODE
|
||||
bool "Enable SPI PSRAM 2T mode"
|
||||
depends on ESP32_SPIRAM
|
||||
default "n"
|
||||
help
|
||||
Enable this option to fix single bit errors inside 64Mbit PSRAM.
|
||||
Some 64Mbit PSRAM chips have a hardware issue in the RAM which
|
||||
causes bit errors at multiple fixed bit positions.
|
||||
Note: If this option is enabled, the 64Mbit PSRAM chip will appear
|
||||
to be 32Mbit in size.
|
||||
Applications will not be affected unless the use the esp_himem
|
||||
APIs, which are not supported in 2T mode.
|
||||
|
||||
endmenu #SPI RAM Config
|
||||
|
||||
menu "Ethernet configuration"
|
||||
depends on ESP32_EMAC
|
||||
|
||||
|
@ -114,6 +114,11 @@ ifeq ($(CONFIG_ESP32_SPIFLASH),y)
|
||||
CHIP_CSRCS += esp32_spiflash.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_ESP32_SPIRAM),y)
|
||||
CHIP_CSRCS += esp32_spiram.c
|
||||
CHIP_CSRCS += esp32_psram.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_ESP32_EMAC),y)
|
||||
CHIP_CSRCS += esp32_emac.c
|
||||
endif
|
||||
|
@ -43,11 +43,16 @@
|
||||
#include <debug.h>
|
||||
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/mm/mm.h>
|
||||
#include <nuttx/board.h>
|
||||
#include <arch/board/board.h>
|
||||
|
||||
#include "xtensa.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
@ -88,5 +93,10 @@ void up_allocate_heap(FAR void **heap_start, size_t *heap_size)
|
||||
#if CONFIG_MM_REGIONS > 1
|
||||
void xtensa_add_region(void)
|
||||
{
|
||||
/* Check for any additional memory regions */
|
||||
|
||||
#if defined(CONFIG_HEAP2_BASE) && defined(CONFIG_HEAP2_SIZE)
|
||||
umm_addregion((FAR void *)CONFIG_HEAP2_BASE, CONFIG_HEAP2_SIZE);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
1758
arch/xtensa/src/esp32/esp32_psram.c
Normal file
1758
arch/xtensa/src/esp32/esp32_psram.c
Normal file
File diff suppressed because it is too large
Load Diff
91
arch/xtensa/src/esp32/esp32_psram.h
Normal file
91
arch/xtensa/src/esp32/esp32_psram.h
Normal file
@ -0,0 +1,91 @@
|
||||
/****************************************************************************
|
||||
* arch/xtensa/src/esp32/esp32_psram.h
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you 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 __ARCH_XTENSA_SRC_ESP32_ESP32_PSRAM_H
|
||||
#define __ARCH_XTENSA_SRC_ESP32_ESP32_PSRAM_H
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
typedef enum
|
||||
{
|
||||
PSRAM_CACHE_F80M_S40M = 0,
|
||||
PSRAM_CACHE_F40M_S40M,
|
||||
PSRAM_CACHE_F80M_S80M,
|
||||
PSRAM_CACHE_MAX,
|
||||
} psram_cache_mode_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
PSRAM_SIZE_16MBITS = 0,
|
||||
PSRAM_SIZE_32MBITS = 1,
|
||||
PSRAM_SIZE_64MBITS = 2,
|
||||
PSRAM_SIZE_MAX,
|
||||
} psram_size_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;
|
||||
|
||||
/* Description: Get PSRAM size
|
||||
* return:
|
||||
* - PSRAM_SIZE_MAX if psram not enabled or not valid
|
||||
* - PSRAM size
|
||||
*/
|
||||
|
||||
psram_size_t psram_get_size(void);
|
||||
|
||||
/* Description: 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
|
||||
* vaddrmode Mode the psram cache works in.
|
||||
* return:
|
||||
* OK on success
|
||||
* EINVAL when VSPI peripheral is needed but cannot be
|
||||
* claimed.
|
||||
*/
|
||||
|
||||
int psram_enable(psram_cache_mode_t mode, psram_vaddr_mode_t
|
||||
vaddrmode);
|
||||
|
||||
#endif /* __ARCH_XTENSA_SRC_ESP32_ESP32_HIMEM_H */
|
385
arch/xtensa/src/esp32/esp32_spiram.c
Normal file
385
arch/xtensa/src/esp32/esp32_spiram.c
Normal file
@ -0,0 +1,385 @@
|
||||
/****************************************************************************
|
||||
* arch/xtensa/src/esp32/esp32_spiflash.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you 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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#ifdef CONFIG_ESP32_SPIRAM
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <errno.h>
|
||||
#include <debug.h>
|
||||
#include <string.h>
|
||||
#include <sys/param.h>
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include "esp32_spiram.h"
|
||||
#include "esp32_psram.h"
|
||||
#include "xtensa.h"
|
||||
#include "xtensa_attr.h"
|
||||
#include "hardware/esp32_soc.h"
|
||||
#include "hardware/esp32_dport.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef MIN
|
||||
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_SMP
|
||||
# define PSRAM_MODE PSRAM_VADDR_MODE_NORMAL
|
||||
#else
|
||||
#if CONFIG_ESP32_MEMMAP_SPIRAM_CACHE_EVENODD
|
||||
# define PSRAM_MODE PSRAM_VADDR_MODE_EVENODD
|
||||
#else
|
||||
# define PSRAM_MODE PSRAM_VADDR_MODE_LOWHIGH
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
/* Let's to assume SPIFLASH SPEED == SPIRAM SPEED for now */
|
||||
|
||||
#if CONFIG_ESP32_SPIRAM_SPEED_40M
|
||||
# define PSRAM_SPEED PSRAM_CACHE_F40M_S40M
|
||||
#elif CONFIG_ESP32_SPIRAM_SPEED_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
|
||||
|
||||
#if defined(CONFIG_BOOT_SDRAM_DATA)
|
||||
extern uint8_t _ext_ram_bss_start;
|
||||
extern uint8_t _ext_ram_bss_end;
|
||||
#endif
|
||||
static bool spiram_inited = false;
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/* If no function in esp_himem.c is used, this function will be linked into
|
||||
* the binary instead of the one in esp_himem.c, automatically making sure
|
||||
* no memory is reserved if no himem function is used.
|
||||
*/
|
||||
|
||||
size_t __attribute__((weak)) esp_himem_reserved_area_size(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int spiram_size_usable_for_malloc(void)
|
||||
{
|
||||
int s = esp_spiram_get_size();
|
||||
|
||||
if (s > 4 * 1024 * 1024)
|
||||
{
|
||||
s = 4 * 1024 * 1024; /* we can map at most 4MiB */
|
||||
}
|
||||
|
||||
return s - esp_himem_reserved_area_size();
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
void IRAM_ATTR esp_spiram_init_cache(void)
|
||||
{
|
||||
/* 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 */
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
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_spiram_size_t esp_spiram_get_chip_size(void)
|
||||
{
|
||||
if (!spiram_inited)
|
||||
{
|
||||
merr("SPI RAM not initialized");
|
||||
return ESP_SPIRAM_SIZE_INVALID;
|
||||
}
|
||||
|
||||
psram_size_t psram_size = psram_get_size();
|
||||
switch (psram_size)
|
||||
{
|
||||
case PSRAM_SIZE_16MBITS:
|
||||
return ESP_SPIRAM_SIZE_16MBITS;
|
||||
|
||||
case PSRAM_SIZE_32MBITS:
|
||||
return ESP_SPIRAM_SIZE_32MBITS;
|
||||
|
||||
case PSRAM_SIZE_64MBITS:
|
||||
return ESP_SPIRAM_SIZE_64MBITS;
|
||||
|
||||
default:
|
||||
return ESP_SPIRAM_SIZE_INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
int esp_spiram_init(void)
|
||||
{
|
||||
int ret;
|
||||
ret = psram_enable(PSRAM_SPEED, PSRAM_MODE);
|
||||
if (ret != OK)
|
||||
{
|
||||
#ifdef CONFIG_ESP32_SPIRAM_IGNORE_NOTFOUND
|
||||
merr("SPI RAM enabled but initialization failed.\
|
||||
Bailing out.");
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* note: this needs to be set before esp_spiram_get_chip_* /
|
||||
* esp_spiram_get_size calls.
|
||||
*/
|
||||
|
||||
spiram_inited = true;
|
||||
|
||||
#if (CONFIG_ESP32_SPIRAM_SIZE != -1)
|
||||
if (esp_spiram_get_size() != CONFIG_ESP32_SPIRAM_SIZE)
|
||||
{
|
||||
merr("Expected %dKiB chip but found %dKiB chip.\
|
||||
Bailing out..\n", CONFIG_ESP32_SPIRAM_SIZE / 1024,
|
||||
esp_spiram_get_size() / 1024);
|
||||
return -EINVAL;
|
||||
}
|
||||
#endif
|
||||
|
||||
minfo("Found %dMBit SPI RAM device\n",
|
||||
(esp_spiram_get_size() * 8) / (1024 * 1024));
|
||||
|
||||
minfo("SPI RAM mode: %s\n",
|
||||
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");
|
||||
|
||||
minfo("PSRAM initialized, cache is in %s mode.\n", \
|
||||
(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");
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* DMA is not supported yet */
|
||||
|
||||
static uint8_t *dma_heap;
|
||||
|
||||
int esp_spiram_reserve_dma_pool(size_t size)
|
||||
{
|
||||
minfo("Reserving pool of %dK of internal memory for DMA/internal\
|
||||
allocations", size / 1024);
|
||||
|
||||
/* Pool may be allocated in multiple non-contiguous chunks, depending on
|
||||
* available RAM
|
||||
*/
|
||||
|
||||
while (size > 0)
|
||||
{
|
||||
size_t next_size = heap_caps_get_largest_free_block(MALLOC_CAP_DMA |
|
||||
MALLOC_CAP_INTERNAL);
|
||||
|
||||
next_size = MIN(next_size, size);
|
||||
|
||||
minfo("Allocating block of size %d bytes", next_size);
|
||||
|
||||
dma_heap = heap_caps_malloc(next_size, MALLOC_CAP_DMA |
|
||||
MALLOC_CAP_INTERNAL);
|
||||
|
||||
if (!dma_heap || next_size == 0)
|
||||
{
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
|
||||
uint32_t caps[] =
|
||||
{
|
||||
0, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL,
|
||||
MALLOC_CAP_8BIT | MALLOC_CAP_32BIT
|
||||
};
|
||||
|
||||
int e = heap_caps_add_region_with_caps(caps, (intptr_t) dma_heap,
|
||||
(intptr_t) dma_heap + next_size - 1);
|
||||
|
||||
if (e != ESP_OK)
|
||||
{
|
||||
return e;
|
||||
}
|
||||
|
||||
size -= next_size;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
size_t esp_spiram_get_size(void)
|
||||
{
|
||||
psram_size_t size = esp_spiram_get_chip_size();
|
||||
|
||||
if (size == PSRAM_SIZE_16MBITS)
|
||||
{
|
||||
return 2 * 1024 * 1024;
|
||||
}
|
||||
|
||||
if (size == PSRAM_SIZE_32MBITS)
|
||||
{
|
||||
return 4 * 1024 * 1024;
|
||||
}
|
||||
|
||||
if (size == PSRAM_SIZE_64MBITS)
|
||||
{
|
||||
return 8 * 1024 * 1024;
|
||||
}
|
||||
|
||||
return CONFIG_ESP32_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. Note that this routine assumes some unique mapping for the first
|
||||
* 2 banks of the PSRAM memory range, as well as the 2 banks after the 2 MiB
|
||||
* mark.
|
||||
*/
|
||||
|
||||
void IRAM_ATTR esp_spiram_writeback_cache(void)
|
||||
{
|
||||
int x;
|
||||
uint32_t regval;
|
||||
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.
|
||||
*/
|
||||
|
||||
regval = getreg32(DPORT_PRO_CACHE_CTRL_REG);
|
||||
|
||||
if ((regval & DPORT_PRO_CACHE_ENABLE) == 0)
|
||||
{
|
||||
cache_was_disabled |= (1 << 0);
|
||||
regval = getreg32(DPORT_PRO_CACHE_CTRL_REG);
|
||||
regval |= (1 << DPORT_PRO_CACHE_ENABLE_S);
|
||||
putreg32(regval, DPORT_PRO_CACHE_CTRL_REG);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
regval = getreg32(DPORT_APP_CACHE_CTRL_REG);
|
||||
|
||||
if ((regval & DPORT_APP_CACHE_ENABLE) == 0)
|
||||
{
|
||||
cache_was_disabled |= (1 << 1);
|
||||
regval = getreg32(DPORT_APP_CACHE_CTRL_REG);
|
||||
regval |= 1 << DPORT_APP_CACHE_ENABLE_S;
|
||||
putreg32(regval, DPORT_APP_CACHE_CTRL_REG);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (PSRAM_MODE != PSRAM_VADDR_MODE_LOWHIGH)
|
||||
/* Single-core and even/odd mode only have 32K of cache evenly distributed
|
||||
* over the address lines. We can clear the cache by just reading 64K
|
||||
* worth of cache lines.
|
||||
*/
|
||||
|
||||
for (x = 0; x < 1024 * 64; x += 32)
|
||||
{
|
||||
i += psram[x];
|
||||
}
|
||||
#else
|
||||
/* Low/high psram cache mode uses one 32K cache for the lowest 2MiB of SPI
|
||||
* flash and another 32K for the highest 2MiB. Clear this by reading from
|
||||
* both regions. 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)];
|
||||
}
|
||||
#endif
|
||||
|
||||
if (cache_was_disabled & (1 << 0))
|
||||
{
|
||||
while (((getreg32(DPORT_PRO_DCACHE_DBUG0_REG) >>
|
||||
(DPORT_PRO_CACHE_STATE_S)) &
|
||||
(DPORT_PRO_CACHE_STATE)) != 1)
|
||||
{
|
||||
};
|
||||
|
||||
regval = getreg32(DPORT_PRO_CACHE_CTRL_REG);
|
||||
regval &= ~(1 << DPORT_PRO_CACHE_ENABLE_S);
|
||||
putreg32(regval, DPORT_PRO_CACHE_CTRL_REG);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
if (cache_was_disabled & (1 << 1))
|
||||
{
|
||||
while (((getreg32(DPORT_APP_DCACHE_DBUG0_REG) >>
|
||||
(DPORT_APP_CACHE_STATE_S)) &
|
||||
(DPORT_APP_CACHE_STATE)) != 1)
|
||||
{
|
||||
};
|
||||
|
||||
regval = getreg32(DPORT_APP_CACHE_CTRL_REG);
|
||||
regval &= ~(1 << DPORT_APP_CACHE_ENABLE_S);
|
||||
putreg32(regval, DPORT_APP_CACHE_CTRL_REG);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* If SPI RAM(PSRAM) has been initialized
|
||||
*
|
||||
* Return:
|
||||
* - true SPI RAM has been initialized successfully
|
||||
* - false SPI RAM hasn't been initialized or initialized failed
|
||||
*/
|
||||
|
||||
bool esp_spiram_is_initialized(void)
|
||||
{
|
||||
return spiram_inited;
|
||||
}
|
||||
|
||||
#endif
|
157
arch/xtensa/src/esp32/esp32_spiram.h
Normal file
157
arch/xtensa/src/esp32/esp32_spiram.h
Normal file
@ -0,0 +1,157 @@
|
||||
/****************************************************************************
|
||||
* arch/xtensa/src/esp32/esp32_spiram.h
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you 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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __ARCH_XTENSA_SRC_ESP32_ESP32_SPIRAM_H
|
||||
#define __ARCH_XTENSA_SRC_ESP32_ESP32_SPIRAM_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "xtensa_attr.h"
|
||||
|
||||
typedef enum
|
||||
{
|
||||
ESP_SPIRAM_SIZE_16MBITS = 0, /* SPI RAM size is 16 MBits */
|
||||
ESP_SPIRAM_SIZE_32MBITS = 1, /* SPI RAM size is 32 MBits */
|
||||
ESP_SPIRAM_SIZE_64MBITS = 2, /* SPI RAM size is 64 MBits */
|
||||
ESP_SPIRAM_SIZE_INVALID, /* SPI RAM size is invalid */
|
||||
} esp_spiram_size_t;
|
||||
|
||||
/* Description: get SPI RAM size
|
||||
* return
|
||||
* - ESP_SPIRAM_SIZE_INVALID if SPI RAM not enabled or not valid
|
||||
* - SPI RAM size
|
||||
*/
|
||||
|
||||
esp_spiram_size_t esp_spiram_get_chip_size(void);
|
||||
|
||||
/* Description: Initialize spiram interface/hardware. Normally called from
|
||||
* cpu_start.c.
|
||||
*
|
||||
* return:
|
||||
* OK on success
|
||||
*/
|
||||
|
||||
int esp_spiram_init(void);
|
||||
|
||||
/* Description: Configure Cache/MMU for access to external SPI RAM.
|
||||
*
|
||||
* Normally this function is called from cpu_start, if
|
||||
* CONFIG_ESP32_SPIRAM_BOOT_INIT option is enabled. Applications which need to
|
||||
* enable SPI RAM at run time can disable CONFIG_ESP32_SPIRAM_BOOT_INIT, and
|
||||
* call this function later.
|
||||
*
|
||||
* Attention this function must be called with flash cache disabled.
|
||||
*/
|
||||
|
||||
void esp_spiram_init_cache(void);
|
||||
|
||||
/* Description: 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(void);
|
||||
|
||||
/* Description Add the initialized SPI RAM to the heap allocator. */
|
||||
|
||||
int esp_spiram_add_to_heapalloc(void);
|
||||
|
||||
/* Description: 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(void);
|
||||
|
||||
/* Description: 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(void);
|
||||
|
||||
/* Description: Reserve a pool of internal memory for specific DMA/internal
|
||||
* allocations.
|
||||
*
|
||||
* param:
|
||||
* size Size of reserved pool in bytes
|
||||
*
|
||||
* return:
|
||||
* - ESP_OK on success
|
||||
* - ESP_ERR_NO_MEM when no memory available for pool
|
||||
*/
|
||||
|
||||
int esp_spiram_reserve_dma_pool(size_t size);
|
||||
|
||||
/* Description: If SPI RAM(PSRAM) has been initialized
|
||||
*
|
||||
* return:
|
||||
* - true SPI RAM has been initialized successfully
|
||||
* - false SPI RAM hasn't been initialized or initialized failed
|
||||
*/
|
||||
|
||||
bool esp_spiram_is_initialized(void);
|
||||
|
||||
/* Description: Set Ext-SRAM-Cache mmu mapping.
|
||||
*
|
||||
* Note that this code lives in IRAM and has a bugfix in respect to the
|
||||
* ROM version of this function (which erroneously refused a vaddr > 2MiB
|
||||
*
|
||||
* param:
|
||||
* int cpu_no : CPU number, 0 for PRO cpu, 1 for APP cpu.
|
||||
* int pod : process identifier. Range 0~7.
|
||||
* unsigned int vaddr : virtual address in CPU address space.
|
||||
* Can be IRam0, IRam1, IRom0 and DRom0 memory
|
||||
* address.
|
||||
* Should be aligned by psize.
|
||||
*
|
||||
* unsigned int paddr : physical address in Ext-SRAM.
|
||||
* Should be aligned by psize.
|
||||
* int psize : page size of flash, in kilobytes. Should be 32 here.
|
||||
* int num : pages to be set.
|
||||
*
|
||||
* unsigned int: error status
|
||||
* 0 : mmu set success
|
||||
* 1 : vaddr or paddr is not aligned
|
||||
* 2 : pid error
|
||||
* 3 : psize error
|
||||
* 4 : mmu table to be written is out of range
|
||||
* 5 : vaddr is out of range
|
||||
*/
|
||||
|
||||
unsigned int IRAM_ATTR
|
||||
cache_sram_mmu_set(int cpu_no, int pid, unsigned int vaddr,
|
||||
unsigned int paddr, int psize, int num);
|
||||
|
||||
#endif /* __ARCH_XTENSA_SRC_ESP32_ESP32_SPIRAM_H */
|
@ -43,6 +43,7 @@
|
||||
#include "esp32_clockconfig.h"
|
||||
#include "esp32_region.h"
|
||||
#include "esp32_start.h"
|
||||
#include "esp32_spiram.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Public Data
|
||||
@ -146,6 +147,18 @@ void IRAM_ATTR __start(void)
|
||||
xtensa_early_serial_initialize();
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_ESP32_SPIRAM_BOOT_INIT)
|
||||
esp_spiram_init_cache();
|
||||
if (esp_spiram_init() != OK)
|
||||
{
|
||||
# if defined(ESP32_SPIRAM_IGNORE_NOTFOUND)
|
||||
mwarn("SPIRAM Initialization failed!\n");
|
||||
# else
|
||||
PANIC();
|
||||
# endif
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Initialize onboard resources */
|
||||
|
||||
esp32_board_initialize();
|
||||
|
1821
arch/xtensa/src/esp32/hardware/efuse_reg.h
Normal file
1821
arch/xtensa/src/esp32/hardware/efuse_reg.h
Normal file
File diff suppressed because it is too large
Load Diff
64
arch/xtensa/src/esp32/hardware/esp32_caps.h
Normal file
64
arch/xtensa/src/esp32/hardware/esp32_caps.h
Normal file
@ -0,0 +1,64 @@
|
||||
/****************************************************************************
|
||||
* arch/xtensa/src/esp32/hardware/esp32_caps.h
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you 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 __ARCH_XTENSA_SRC_ESP32_HARDWARE_ESP32_CAPS_H
|
||||
#define __ARCH_XTENSA_SRC_ESP32_HARDWARE_ESP32_CAPS_H
|
||||
|
||||
#define SOC_SPI_PERIPH_NUM 3
|
||||
#define SOC_SPI_DMA_CHAN_NUM 2
|
||||
#define SOC_SPI_PERIPH_CS_NUM(i) 3
|
||||
|
||||
#define SPI_FUNC_NUM 1
|
||||
#define SPI_IOMUX_PIN_NUM_MISO 7
|
||||
#define SPI_IOMUX_PIN_NUM_MOSI 8
|
||||
#define SPI_IOMUX_PIN_NUM_CLK 6
|
||||
#define SPI_IOMUX_PIN_NUM_CS 11
|
||||
#define SPI_IOMUX_PIN_NUM_WP 10
|
||||
#define SPI_IOMUX_PIN_NUM_HD 9
|
||||
|
||||
#define HSPI_FUNC_NUM 1
|
||||
|
||||
/* For D2WD and PICO-D4 chip */
|
||||
|
||||
#define SPI_D2WD_PIN_NUM_MISO 17
|
||||
#define SPI_D2WD_PIN_NUM_MOSI 8
|
||||
#define SPI_D2WD_PIN_NUM_CLK 6
|
||||
#define SPI_D2WD_PIN_NUM_CS 16
|
||||
#define SPI_D2WD_PIN_NUM_WP 7
|
||||
#define SPI_D2WD_PIN_NUM_HD 11
|
||||
|
||||
#define HSPI_IOMUX_PIN_NUM_MISO 12
|
||||
#define HSPI_IOMUX_PIN_NUM_MOSI 13
|
||||
#define HSPI_IOMUX_PIN_NUM_CLK 14
|
||||
#define HSPI_IOMUX_PIN_NUM_CS 15
|
||||
#define HSPI_IOMUX_PIN_NUM_WP 2
|
||||
#define HSPI_IOMUX_PIN_NUM_HD 4
|
||||
|
||||
#define VSPI_FUNC_NUM 1
|
||||
#define VSPI_IOMUX_PIN_NUM_MISO 19
|
||||
#define VSPI_IOMUX_PIN_NUM_MOSI 23
|
||||
#define VSPI_IOMUX_PIN_NUM_CLK 18
|
||||
#define VSPI_IOMUX_PIN_NUM_CS 5
|
||||
#define VSPI_IOMUX_PIN_NUM_WP 22
|
||||
#define VSPI_IOMUX_PIN_NUM_HD 21
|
||||
|
||||
#define SOC_SPI_MAXIMUM_BUFFER_SIZE 64
|
||||
|
||||
#endif /* __ARCH_XTENSA_SRC_ESP32_HARDWARE_ESP32_CAPS_H */
|
@ -246,6 +246,30 @@
|
||||
#define DR_REG_PWM3_BASE 0x3ff70000
|
||||
#define PERIPHS_SPI_ENCRYPT_BASEADDR DR_REG_SPI_ENCRYPT_BASE
|
||||
|
||||
/* Overall memory map */
|
||||
#define SOC_DROM_LOW 0x3f400000
|
||||
#define SOC_DROM_HIGH 0x3f800000
|
||||
#define SOC_DRAM_LOW 0x3ffae000
|
||||
#define SOC_DRAM_HIGH 0x40000000
|
||||
#define SOC_IROM_LOW 0x400d0000
|
||||
#define SOC_IROM_HIGH 0x40400000
|
||||
#define SOC_IROM_MASK_LOW 0x40000000
|
||||
#define SOC_IROM_MASK_HIGH 0x40064f00
|
||||
#define SOC_CACHE_PRO_LOW 0x40070000
|
||||
#define SOC_CACHE_PRO_HIGH 0x40078000
|
||||
#define SOC_CACHE_APP_LOW 0x40078000
|
||||
#define SOC_CACHE_APP_HIGH 0x40080000
|
||||
#define SOC_IRAM_LOW 0x40080000
|
||||
#define SOC_IRAM_HIGH 0x400a0000
|
||||
#define SOC_RTC_IRAM_LOW 0x400c0000
|
||||
#define SOC_RTC_IRAM_HIGH 0x400c2000
|
||||
#define SOC_RTC_DRAM_LOW 0x3ff80000
|
||||
#define SOC_RTC_DRAM_HIGH 0x3ff82000
|
||||
#define SOC_RTC_DATA_LOW 0x50000000
|
||||
#define SOC_RTC_DATA_HIGH 0x50002000
|
||||
#define SOC_EXTRAM_DATA_LOW 0x3f800000
|
||||
#define SOC_EXTRAM_DATA_HIGH 0x3fc00000
|
||||
|
||||
/* Interrupt hardware source table
|
||||
* This table is decided by hardware, don't touch this.
|
||||
*/
|
||||
|
96
arch/xtensa/src/esp32/rom/esp32_efuse.h
Normal file
96
arch/xtensa/src/esp32/rom/esp32_efuse.h
Normal file
@ -0,0 +1,96 @@
|
||||
/****************************************************************************
|
||||
* arch/xtensa/src/esp32/rom/esp32_efuse.h
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you 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 __XTENSA_SRC_ESP32_ROM_ESP32_EFUSE_H
|
||||
#define __XTENSA_SRC_ESP32_ROM_ESP32_EFUSE_H
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ets_efuse_read_op
|
||||
****************************************************************************/
|
||||
|
||||
void ets_efuse_read_op(void);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ets_efuse_program_op
|
||||
****************************************************************************/
|
||||
|
||||
void ets_efuse_program_op(void);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ets_efuse_get_8m_clock
|
||||
****************************************************************************/
|
||||
|
||||
uint32_t ets_efuse_get_8m_clock(void);
|
||||
|
||||
/****************************************************************************
|
||||
* name: ets_efuse_get_spiconfig
|
||||
****************************************************************************/
|
||||
|
||||
uint32_t ets_efuse_get_spiconfig(void);
|
||||
|
||||
#define EFUSE_SPICFG_SPI_DEFAULTS 0
|
||||
#define EFUSE_SPICFG_HSPI_DEFAULTS 1
|
||||
|
||||
#define EFUSE_SPICFG_RET_SPICLK_MASK 0x3f
|
||||
#define EFUSE_SPICFG_RET_SPICLK_SHIFT 0
|
||||
#define EFUSE_SPICFG_RET_SPICLK(ret) (((ret) >> EFUSE_SPICFG_RET_SPICLK_SHIFT) & EFUSE_SPICFG_RET_SPICLK_MASK)
|
||||
|
||||
#define EFUSE_SPICFG_RET_SPIQ_MASK 0x3f
|
||||
#define EFUSE_SPICFG_RET_SPIQ_SHIFT 6
|
||||
#define EFUSE_SPICFG_RET_SPIQ(ret) (((ret) >> EFUSE_SPICFG_RET_SPIQ_SHIFT) & EFUSE_SPICFG_RET_SPIQ_MASK)
|
||||
|
||||
#define EFUSE_SPICFG_RET_SPID_MASK 0x3f
|
||||
#define EFUSE_SPICFG_RET_SPID_SHIFT 12
|
||||
#define EFUSE_SPICFG_RET_SPID(ret) (((ret) >> EFUSE_SPICFG_RET_SPID_SHIFT) & EFUSE_SPICFG_RET_SPID_MASK)
|
||||
|
||||
#define EFUSE_SPICFG_RET_SPICS0_MASK 0x3f
|
||||
#define EFUSE_SPICFG_RET_SPICS0_SHIFT 18
|
||||
#define EFUSE_SPICFG_RET_SPICS0(ret) (((ret) >> EFUSE_SPICFG_RET_SPICS0_SHIFT) & EFUSE_SPICFG_RET_SPICS0_MASK)
|
||||
|
||||
#define EFUSE_SPICFG_RET_SPIHD_MASK 0x3f
|
||||
#define EFUSE_SPICFG_RET_SPIHD_SHIFT 24
|
||||
#define EFUSE_SPICFG_RET_SPIHD(ret) (((ret) >> EFUSE_SPICFG_RET_SPIHD_SHIFT) & EFUSE_SPICFG_RET_SPIHD_MASK)
|
||||
|
||||
/****************************************************************************
|
||||
* name: eps_crc8
|
||||
****************************************************************************/
|
||||
|
||||
unsigned char esp_crc8(unsigned char const *p, unsigned int len);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __XTENSA_SRC_ESP32_ROM_ESP32_EFUSE_H */
|
Loading…
Reference in New Issue
Block a user