blob: 350518808320b6b4f8a679c4df755b8d2d435f86 [file] [log] [blame]
/****************************************************************************
* arch/xtensa/src/esp32s3/esp32s3_textheap.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>
#include <nuttx/arch.h>
#include <nuttx/fs/procfs.h>
#include <nuttx/mm/mm.h>
#include <sys/types.h>
#include <debug.h>
#include <nuttx/kmalloc.h>
#include "hal/cache_hal.h"
#include "hardware/esp32s3_soc.h"
#ifdef CONFIG_ESP32S3_RTC_HEAP
# include "esp32s3_rtcheap.h"
#endif
#include "esp32s3_spiram.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#define EXTRAM_INSTRUCTION_BUS_LOW 0x42000000
#define EXTRAM_INSTRUCTION_BUS_HIGH 0x44000000
#define EXTRAM_D_I_BUS_OFFSET 0x6000000
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: up_textheap_memalign
*
* Description:
* memalign requests more than enough space from malloc, finds a region
* within that chunk that meets the alignment request and then frees any
* leading or trailing space in text heap.
*
* The alignment argument must be a power of two (not checked). 8-byte
* alignment is guaranteed by normal malloc calls.
*
* Parameters:
* align - Requested alignment.
* size - Size (in bytes) of the memory region to be allocated.
*
* Return Value:
* Address of the allocated address. NULL, if allocation fails.
*
****************************************************************************/
void *up_textheap_memalign(size_t align, size_t size)
{
void *ret = NULL;
/* Prioritise allocating from RTC. If that fails, allocate from the
* main heap.
*/
#ifdef CONFIG_ESP32S3_RTC_HEAP
ret = esp32s3_rtcheap_memalign(align, size);
#endif
if (ret == NULL)
{
ret = kmm_memalign(align, size);
if (ret)
{
/* kmm_memalign buffer is at the Data bus offset. Adjust it so we
* can access it from the Instruction bus.
*/
uintptr_t addr = (uintptr_t)ret;
if (SOC_DIRAM_DRAM_LOW <= addr && addr < SOC_DIRAM_DRAM_HIGH)
{
addr = MAP_DRAM_TO_IRAM(addr);
}
else
{
/* extram */
addr += EXTRAM_D_I_BUS_OFFSET;
}
ret = (void *)addr;
}
}
return ret;
}
/****************************************************************************
* Name: up_textheap_free
*
* Description:
* Free memory from the text heap.
*
* Parameters:
* mem - Address to be freed.
*
****************************************************************************/
void up_textheap_free(void *p)
{
if (p)
{
#ifdef CONFIG_ESP32S3_RTC_HEAP
if (esp32s3_ptr_rtc(p))
{
esp32s3_rtcheap_free(p);
}
else
#endif
{
p = up_textheap_data_address(p);
kmm_free(p);
}
}
}
/****************************************************************************
* Name: up_textheap_heapmember
*
* Description:
* Check if an address lies in text heap.
*
* Parameters:
* mem - The address to check.
*
* Return Value:
* True if the address is a member of the text heap. False if not.
*
****************************************************************************/
bool up_textheap_heapmember(void *p)
{
if (p == NULL)
{
return false;
}
#ifdef CONFIG_ESP32S3_RTC_HEAP
if (esp32s3_ptr_rtc(p))
{
return esp32s3_rtcheap_heapmember(p);
}
#endif
p = up_textheap_data_address(p);
return kmm_heapmember(p);
}
/****************************************************************************
* Name: up_textheap_data_address
*
* Description:
* If an instruction bus address is specified, return the corresponding
* data bus address. Otherwise, return the given address as it is.
*
* For some platforms, up_textheap_memalign() might return memory regions
* with separate instruction/data bus mappings. In that case,
* up_textheap_memalign() returns the address of the instruction bus
* mapping.
* The instruction bus mapping might provide only limited data access.
* (For example, only read-only, word-aligned access.)
* You can use up_textheap_data_address() to query the corresponding data
* bus mapping.
*
****************************************************************************/
void *up_textheap_data_address(void *p)
{
uintptr_t addr = (uintptr_t)p;
if (SOC_DIRAM_IRAM_LOW <= addr && addr < SOC_DIRAM_IRAM_HIGH)
{
addr = MAP_IRAM_TO_DRAM(addr);
}
else if (EXTRAM_INSTRUCTION_BUS_LOW <= addr &&
addr < EXTRAM_INSTRUCTION_BUS_HIGH)
{
/* extram */
addr -= EXTRAM_D_I_BUS_OFFSET;
}
return (void *)addr;
}
/****************************************************************************
* Name: up_textheap_data_sync
*
* Description:
* Ensure modifications made on the data bus addresses (the addresses
* returned by up_textheap_data_address) fully visible on the corresponding
* instruction bus addresses.
*
****************************************************************************/
IRAM_ATTR void up_textheap_data_sync(void)
{
irqstate_t flags = enter_critical_section();
#ifdef CONFIG_ESP32S3_SPIRAM
esp_spiram_writeback_cache();
#endif
cache_hal_disable(CACHE_TYPE_INSTRUCTION);
cache_hal_enable(CACHE_TYPE_INSTRUCTION);
leave_critical_section(flags);
}
/****************************************************************************
* Name: up_copy_section
*
* Description:
* This function copies a section from a general temporary buffer (src) to
* a specific address (dest). This is typically used in architectures that
* require specific handling of memory sections.
*
* Input Parameters:
* dest - A pointer to the destination where the data needs to be copied.
* src - A pointer to the source from where the data needs to be copied.
* n - The number of bytes to be copied from src to dest.
*
* Returned Value:
* Zero (OK) on success; a negated errno value on failure.
*
****************************************************************************/
#if defined(CONFIG_ARCH_USE_COPY_SECTION)
int up_copy_section(void *dest, const void *src, size_t n)
{
memcpy(up_textheap_data_address(dest), src, n);
return OK;
}
#endif