chore: migrate project into clean repository

This commit is contained in:
yuuux
2026-08-13 16:50:52 +08:00
commit d1d25a09e7
27405 changed files with 9422808 additions and 0 deletions

View File

@@ -0,0 +1,14 @@
cmake_minimum_required(VERSION 3.13)
set(LISTENAI_MODULES_DIR_LIST
${CMAKE_CURRENT_SOURCE_DIR}/src
)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
find_package(listenai-cmake REQUIRED HINTS $ENV{ARCS_BASE})
project(boot)
listenai_add_executable(${PROJECT_NAME})
listenai_set_linker_script(${CMAKE_CURRENT_SOURCE_DIR}/src/linker.ld)

View File

@@ -0,0 +1,2 @@
osource "$LISTENAI_MODULES"
rsource "Kconfig.boot"

View File

@@ -0,0 +1,49 @@
config BOOT_AP_ENTRY
hex "AP entry"
default 0
config BOOT_CP_ENTRY
hex "CP entry"
default 0
depends on !MEM_CONFIG
config BOOT_FLASH_SIZE
hex "Flash size"
default 0x4000
choice
prompt "boot log level"
default BOOT_LOG_LVL_ERR
config BOOT_LOG_LVL_NON
bool "non"
config BOOT_LOG_LVL_ERR
bool "err"
config BOOT_LOG_LVL_WRN
bool "wrn"
config BOOT_LOG_LVL_INF
bool "inf"
config BOOT_LOG_LVL_DBG
bool "dbg"
config BOOT_UART_PORT
int "boot log port"
default SYSLOG_UART_PORT if BOOT
default 0
config BOOT_UART_TX_PIN
int "boot uart tx pin"
default SYSLOG_UART_TX_PIN if BOOT
default 3
config BOOT_UART_BAUDRATE
int "boot log baud rate"
default SYSLOG_UART_BAUDRATE if BOOT
default 921600
config BOOT_UART_PIN_FUNC_SEL
int "boot log pin func sel"
default SYSLOG_UART_TX_PIN_FUNC_SEL if BOOT
default 2
endchoice

177
arcs-sdk/startup/boot/build.sh Executable file
View File

@@ -0,0 +1,177 @@
#!/bin/bash
set -e
usage() {
echo "使用方式: $0 [选项]"
echo "选项:"
echo " -S, --Source <path> 指定项目源码路径 (默认为当前脚本所在目录)"
echo " -t, --target <target> 指定构建目标 (如 menuconfig)"
echo " -C, --Clean 清理构建目录"
echo " -B, --build 构建输出目录"
echo " -h, --help 显示此帮助信息"
echo " -r, --release 以 Release 模式构建 (移除 DEBUG_PATH 信息)"
echo " -w, --warnings-as-errors 将警告视为错误"
echo " -D<var>=<value> 传递 CMake 变量 (可多次使用)"
echo ""
echo "示例:"
echo " $0 -S samples/helloworld -DBOARD=arcs_mini 指定板型构建"
echo " $0 -S samples/helloworld -DBOARD=arcs_evb 使用 EVB 板型"
echo " $0 -S samples/helloworld -t menuconfig -DBOARD=arcs_mini 运行 menuconfig"
echo " $0 -C -S samples/helloworld -DBOARD=arcs_mini 清理并重新构建"
echo " $0 -S samples/helloworld -DBOARD=my_board -DBOARD_SEARCH_PATH=/path/to/boards 使用自定义板型"
exit 1
}
SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)
PROJECT_PATH="$SCRIPT_DIR"
TARGET=""
CLEAN=false
OUTPUT="build"
WARNINGS_AS_ERRORS=false
RELEASE=false
ARCS_BASE_DIR_NAME="arcs-sdk"
ARCS_DEV_TOOLS_DIR_NAME="listenai-dev-tools"
ARCS_DEV_TOOL_TOOLCHAIN_DIR_NAME="gcc"
ARCS_DEV_TOOL_LISTENAI_TOOLS_DIR_NAME="listenai-tools"
find_arcs_base() {
local current_dir=$(cd "$(dirname "$0")" && pwd)
local dir_name="$ARCS_BASE_DIR_NAME"
while [ "$current_dir" != "/" ]; do
if [ -d "$current_dir/$dir_name" ]; then
echo "Found ARCS_BASE: $current_dir/$dir_name"
export ARCS_BASE="$current_dir/$dir_name"
return 0
fi
current_dir=$(dirname "$current_dir")
done
echo "ARCS_BASE not found, Please add ARCS_BASE environment variable or set ARCS_BASE_DIR_NAME to the correct directory."
echo "Current Target ARCS_BASE directory name: $ARCS_BASE_DIR_NAME."
exit 1
}
find_dev_tools() {
local current_dir=$(cd "$(dirname "$0")" && pwd)
local dir_name="$ARCS_DEV_TOOLS_DIR_NAME"
echo "trying to find $dir_name in parent directories..."
while [ "$current_dir" != "/" ]; do
if [ -d "$current_dir/$dir_name" ]; then
echo "Found $dir_name: $current_dir/$dir_name"
if [ -d "$current_dir/$dir_name/$ARCS_DEV_TOOL_LISTENAI_TOOLS_DIR_NAME" ]; then
echo "Found LISTENAI_TOOLS_PATH: $current_dir/$dir_name/$ARCS_DEV_TOOL_LISTENAI_TOOLS_DIR_NAME"
export LISTENAI_TOOLS_PATH="$current_dir/$dir_name/$ARCS_DEV_TOOL_LISTENAI_TOOLS_DIR_NAME"
fi
if [ -d "$current_dir/$dir_name/$ARCS_DEV_TOOL_TOOLCHAIN_DIR_NAME" ]; then
echo "Found NUCLEI_TOOLCHAIN_PATH: $current_dir/$dir_name/$ARCS_DEV_TOOL_TOOLCHAIN_DIR_NAME"
export NUCLEI_TOOLCHAIN_PATH="$current_dir/$dir_name/$ARCS_DEV_TOOL_TOOLCHAIN_DIR_NAME"
fi
return 0
fi
current_dir=$(dirname "$current_dir")
done
}
while [[ $# -gt 0 ]]; do
case $1 in
-S|--Source)
PROJECT_PATH="$2"
shift 2
;;
-B|--build)
OUTPUT="$2"
shift 2
;;
-t|--target)
TARGET="$2"
shift 2
;;
-C|--Clean)
CLEAN=true
shift 1
;;
-w|--warnings-as-errors)
WARNINGS_AS_ERRORS=true
shift 1
;;
-h|--help)
usage
;;
-r|--release)
RELEASE=true
shift 1
;;
-D*)
CMAKE_VARS+=("$1")
shift 1
;;
*)
echo "未知参数: $1"
usage
;;
esac
done
echo "Source: $PROJECT_PATH"
echo "Target: $TARGET"
echo "Clean : $CLEAN"
if [ -z "$LISTENAI_TOOLS_PATH" ] || [ -z "$NUCLEI_TOOLCHAIN_PATH" ]; then
find_dev_tools
fi
if [ -z "${LISTENAI_TOOLS_PATH}" ]; then
export LISTENAI_TOOLS_PATH="请添加 LISTENAI_TOOLS_PATH 环境变量,或在此行设置正确的路径"
echo "请添加 LISTENAI_TOOLS_PATH 环境变量或者修改脚本后, 注释脚本第 $LINENO";exit 1;
fi
if [ -z "${NUCLEI_TOOLCHAIN_PATH}" ]; then
export NUCLEI_TOOLCHAIN_PATH="请添加 NUCLEI_TOOLCHAIN_PATH 环境变量,或在此行设置正确的路径"
echo "请添加 NUCLEI_TOOLCHAIN_PATH 环境变量或者修改脚本后, 注释脚本第 $LINENO";exit 1;
fi
############### 下面代码不用修改 ##################
# 构建工具的位置
CMAKE_PROGRAM="$LISTENAI_TOOLS_PATH/cmake/bin/cmake"
NINJA_PROGRAM="$LISTENAI_TOOLS_PATH/ninja/ninja"
# 配置环境变量 ARCS_BASE
if [ -z "$ARCS_BASE" ]; then
find_arcs_base
fi
if [ "$CLEAN" = true ]; then
rm -rf $OUTPUT
fi
# Initialize CMAKE_VARS array if it doesn't exist
declare -a CMAKE_VARS
# Add warnings-as-errors flag if enabled
if [ "$WARNINGS_AS_ERRORS" = true ]; then
CMAKE_VARS+=("-DCMAKE_C_FLAGS=-Werror")
CMAKE_VARS+=("-DCMAKE_CXX_FLAGS=-Werror")
echo "Treating warnings as errors"
fi
# Add release flags if enabled
if [ "$RELEASE" = true ]; then
CMAKE_VARS+=("-DENABLE_DEBUG_PATH=OFF")
echo "Release mode enabled (-DENABLE_DEBUG_PATH=OFF)"
fi
$CMAKE_PROGRAM -B "$OUTPUT" -G Ninja -S "$PROJECT_PATH" \
-DCMAKE_MAKE_PROGRAM="$NINJA_PROGRAM" \
"${CMAKE_VARS[@]}"
if [ -z "$TARGET" ]; then
$CMAKE_PROGRAM --build "$OUTPUT" -j4
else
$CMAKE_PROGRAM --build "$OUTPUT" --target "$TARGET"
fi

View File

@@ -0,0 +1,2 @@
# 项目可根据需要在此文件中设置对应的配置
CONFIG_LINK_OPTION_LISTENAI_LIBRARY_NONE=y

View File

@@ -0,0 +1,4 @@
tests:
startup.boot:
build_only: true

View File

@@ -0,0 +1,50 @@
enable_language(ASM)
listenai_library_named(boot_app)
listenai_compile_definitions(-DCHIP=4 -DIC_BOARD=1 -DPSRAM_LOG_CHECK=0)
# 添加从父项目传递的额外编译定义
if(DEFINED BOOT_EXTRA_DEFINES)
string(REPLACE "|" ";" BOOT_EXTRA_DEFINES_LIST "${BOOT_EXTRA_DEFINES}")
foreach(define IN LISTS BOOT_EXTRA_DEFINES_LIST)
listenai_compile_definitions(${define})
endforeach()
endif()
set(ENV{ARCS_SOC_BASE} $ENV{ARCS_BASE}/soc/arcs)
listenai_include_directories(
$ENV{ARCS_SOC_BASE}/hal/chip/arcs/bsp
$ENV{ARCS_SOC_BASE}/hal/chip/arcs/include
$ENV{ARCS_SOC_BASE}/hal/include/bsp
$ENV{ARCS_SOC_BASE}/hal/include/NMSIS/Core/Include
$ENV{ARCS_SOC_BASE}/hal/include/bsp
$ENV{ARCS_SOC_BASE}/hal/include/NMSIS/Core/Include
$ENV{ARCS_SOC_BASE}/hal/include/NMSIS/DSP/Include
$ENV{ARCS_SOC_BASE}/hal/include/NMSIS/DSP/Include/dsp
$ENV{ARCS_SOC_BASE}/hal/include/NMSIS/DSP/PrivateInclude
$ENV{ARCS_SOC_BASE}/hal/chip/arcs/bsp/
$ENV{ARCS_SOC_BASE}/hal/chip/arcs/include/
$ENV{ARCS_SOC_BASE}/hal/chip/arcs/include/utils
$ENV{ARCS_SOC_BASE}/hal/chip/arcs/include/register
$ENV{ARCS_SOC_BASE}/hal/chip/arcs/driver/private_include
$ENV{ARCS_SOC_BASE}/hal/modules/debug/include/
$ENV{ARCS_SOC_BASE}/hal/modules/debug/
)
listenai_include_directories(
${CMAKE_CURRENT_SOURCE_DIR}/
)
listenai_library_sources(
boot.S
boot.c
boot_log.c
cache.c
$ENV{ARCS_SOC_BASE}/hal/chip/arcs/driver/system/PSRAMManager.c
$ENV{ARCS_SOC_BASE}/hal/chip/arcs/driver/cmu/clock_config.c
$ENV{ARCS_SOC_BASE}/hal/chip/arcs/driver/cmu/ClockManager.c
$ENV{ARCS_SOC_BASE}/hal/chip/arcs/driver/iomux/IOMuxManager.c
)

View File

@@ -0,0 +1,212 @@
#include "riscv_encoding.h"
.macro DECLARE_INT_HANDLER INT_HDL_NAME
#if defined(__riscv_xlen) && (__riscv_xlen == 32)
.word \INT_HDL_NAME
#else
.dword \INT_HDL_NAME
#endif
.endm
.section .vtable
.globl vector_base
.type vector_base, @object
vector_base:
#ifndef VECTOR_TABLE_REMAPPED
j _start /* 0: Reserved, Jump to _start when reset for vector table not remapped cases.*/
.align LOG_REGBYTES /* Need to align 4 byte for RV32, 8 Byte for RV64 */
#else
DECLARE_INT_HANDLER irq_default_handler /* 0: Reserved, default handler for vector table remapped cases */
#endif
DECLARE_INT_HANDLER irq_default_handler /* 1: Reserved */
DECLARE_INT_HANDLER irq_default_handler /* 2: Reserved */
#ifndef CFG_RTOS
DECLARE_INT_HANDLER irq_default_handler /* 3: Machine software interrupt */
#else
DECLARE_INT_HANDLER irq_default_handler /* 3: Machine software interrupt, vector mode for FreeRTOS implementation */
#endif
DECLARE_INT_HANDLER irq_default_handler /* 4: Reserved */
DECLARE_INT_HANDLER irq_default_handler /* 5: Reserved */
DECLARE_INT_HANDLER irq_default_handler /* 6: Reserved */
DECLARE_INT_HANDLER irq_default_handler /* 7: Machine timer interrupt */
DECLARE_INT_HANDLER irq_default_handler /* 8: Reserved */
DECLARE_INT_HANDLER irq_default_handler /* 9: Reserved */
DECLARE_INT_HANDLER irq_default_handler /* 10: Reserved */
DECLARE_INT_HANDLER irq_default_handler /* 11: Reserved */
DECLARE_INT_HANDLER irq_default_handler /* 12: Reserved */
DECLARE_INT_HANDLER irq_default_handler /* 13: Reserved */
DECLARE_INT_HANDLER irq_default_handler /* 14: Reserved */
DECLARE_INT_HANDLER irq_default_handler /* 15: Reserved */
DECLARE_INT_HANDLER irq_default_handler /* 16: Reserved */
DECLARE_INT_HANDLER irq_default_handler /* 17: Reserved */
DECLARE_INT_HANDLER irq_default_handler /* 18: Reserved */
DECLARE_INT_HANDLER irq_default_handler /* 19: Interrupt 19 */
DECLARE_INT_HANDLER irq_default_handler /* 20: Interrupt 20 */
DECLARE_INT_HANDLER irq_default_handler /* 21: Interrupt 21 */
DECLARE_INT_HANDLER irq_default_handler /* 22: Interrupt 22 */
DECLARE_INT_HANDLER irq_default_handler /* 23: Interrupt 23 */
DECLARE_INT_HANDLER irq_default_handler /* 24: Interrupt 24 */
DECLARE_INT_HANDLER irq_default_handler /* 25: Interrupt 25 */
DECLARE_INT_HANDLER irq_default_handler /* 26: Interrupt 26 */
DECLARE_INT_HANDLER irq_default_handler /* 27: Interrupt 27 */
DECLARE_INT_HANDLER irq_default_handler /* 28: Interrupt 28 */
DECLARE_INT_HANDLER irq_default_handler /* 29: Interrupt 29 */
DECLARE_INT_HANDLER irq_default_handler /* 30: Interrupt 30 */
DECLARE_INT_HANDLER irq_default_handler /* 31: Interrupt 31 */
DECLARE_INT_HANDLER irq_default_handler /* 32: Interrupt 32 */
DECLARE_INT_HANDLER irq_default_handler /* 33: Interrupt 33 */
DECLARE_INT_HANDLER irq_default_handler /* 34: Interrupt 34 */
DECLARE_INT_HANDLER irq_default_handler /* 35: Interrupt 35 */
DECLARE_INT_HANDLER irq_default_handler /* 36: Interrupt 36 */
DECLARE_INT_HANDLER irq_default_handler /* 37: Interrupt 37 */
DECLARE_INT_HANDLER irq_default_handler /* 38: Interrupt 38 */
DECLARE_INT_HANDLER irq_default_handler /* 39: Interrupt 39 */
DECLARE_INT_HANDLER irq_default_handler /* 40: Interrupt 40 */
DECLARE_INT_HANDLER irq_default_handler /* 41: Interrupt 41 */
DECLARE_INT_HANDLER irq_default_handler /* 42: Interrupt 42 */
DECLARE_INT_HANDLER irq_default_handler /* 43: Interrupt 43 */
DECLARE_INT_HANDLER irq_default_handler /* 44: Interrupt 44 */
DECLARE_INT_HANDLER irq_default_handler /* 45: Interrupt 45 */
DECLARE_INT_HANDLER irq_default_handler /* 46: Interrupt 46 */
DECLARE_INT_HANDLER irq_default_handler /* 47: Interrupt 47 */
DECLARE_INT_HANDLER irq_default_handler /* 48: Interrupt 48 */
DECLARE_INT_HANDLER irq_default_handler /* 49: Interrupt 49 */
DECLARE_INT_HANDLER irq_default_handler /* 50: Interrupt 50 */
DECLARE_INT_HANDLER irq_default_handler /* 51: Interrupt 51 */
DECLARE_INT_HANDLER irq_default_handler /* 52: Interrupt 52 */
DECLARE_INT_HANDLER irq_default_handler /* 53: Interrupt 53 */
DECLARE_INT_HANDLER irq_default_handler /* 54: Interrupt 54 */
DECLARE_INT_HANDLER irq_default_handler /* 55: Interrupt 55 */
DECLARE_INT_HANDLER irq_default_handler /* 56: Interrupt 56 */
DECLARE_INT_HANDLER irq_default_handler /* 57: Interrupt 57 */
DECLARE_INT_HANDLER irq_default_handler /* 58: Interrupt 58 */
DECLARE_INT_HANDLER irq_default_handler /* 59: Interrupt 59 */
DECLARE_INT_HANDLER irq_default_handler /* 60: Interrupt 60 */
DECLARE_INT_HANDLER irq_default_handler /* 61: Interrupt 61 */
DECLARE_INT_HANDLER irq_default_handler /* 62: Interrupt 62 */
DECLARE_INT_HANDLER irq_default_handler /* 63: Interrupt 63 */
DECLARE_INT_HANDLER irq_default_handler /* 64: Interrupt 64 */
DECLARE_INT_HANDLER irq_default_handler /* 65: Interrupt 65 */
DECLARE_INT_HANDLER irq_default_handler /* 66: Interrupt 66 */
DECLARE_INT_HANDLER irq_default_handler /* 67: Interrupt 67 */
DECLARE_INT_HANDLER irq_default_handler /* 68: Interrupt 68 */
DECLARE_INT_HANDLER irq_default_handler /* 69: Interrupt 69 */
DECLARE_INT_HANDLER irq_default_handler /* 70: Interrupt 70 */
DECLARE_INT_HANDLER irq_default_handler /* 71: Interrupt 71 */
DECLARE_INT_HANDLER irq_default_handler /* 72: Interrupt 72 */
DECLARE_INT_HANDLER irq_default_handler /* 73: Interrupt 73 */
DECLARE_INT_HANDLER irq_default_handler /* 74: Interrupt 74 */
DECLARE_INT_HANDLER irq_default_handler /* 75: Interrupt 75 */
DECLARE_INT_HANDLER irq_default_handler /* 76: Interrupt 76 */
DECLARE_INT_HANDLER irq_default_handler /* 77: Interrupt 77 */
.word 0 /* 78: reserved */
.word 0 /* 79: reserved */
/* Header */
.ascii "Hr" /* byte(0~1): header mark */
.byte 0x01, 0x04 /* byte(2~3): header version 1.4 */
.word 0 /* byte(4~7): image size */
.word vector_base /* byte(8~11): image vma */
.byte 0x01, 0x00, 0x03 /* byte(12~14): image version 1.0.1 */
.byte 0x00 /* byte(15~15): image flags */
.ascii "ARCS", "_APP", "\0\0\0\0" /* byte(16~27): image name */
.short 0x00 /* byte(28~29): patch_offset*/
.short 0x00 /* byte(30~31): gpt_offset */
.word 0 /* byte(32~59): reserved */
.word 0 /* byte(36~39): reserved */
.word 0 /* byte(40~43): reserved */
.word 0 /* byte(44~47): reserved */
.word 0 /* byte(48~51): reserved */
.word 0 /* byte(52~55): reserved */
.word 0 /* byte(56~59): reserved */
.short 0x0 /* byte(60~61): header check sum */
.short 0x0 /* byte(62~63): vector check sum */
/* Reset Handler called on controller reset */
.section .init
.section .init
.section .init
.globl _start
.type _start, @function
_start:
/* ===== Startup Stage 1 ===== */
/* Disable Global Interrupt */
csrc CSR_MSTATUS, MSTATUS_MIE
/* Initialize GP and TP */
.option push
.option norelax
la gp, __global_pointer$
la tp, __tls_base
.option pop
/* Set correct sp for current cpu */
la sp, __StackTop
/* Set the the NMI base mnvec to share with mtvec by setting CSR_MMISC_CTL bit 9 NMI_CAUSE_FFF to 1 */
li t0, MMISC_CTL_NMI_CAUSE_FFF
csrs CSR_MMISC_CTL, t0
/* Intialize ECLIC vector interrupt base address mtvt to vector_base */
la t0, vector_base
csrw CSR_MTVT, t0
/* Set ECLIC non-vector entry to be controlled by mtvt2 CSR register.
* Intialize ECLIC non-vector interrupt base address mtvt2 to irq_entry. */
la t0, irq_entry
csrw CSR_MTVT2, t0
csrs CSR_MTVT2, 0x1
/* Set Exception Entry MTVEC to early_exc_entry Due to settings above, Exception and NMI will share common entry.
* This early_exc_entry is only used during early boot stage before main */
la t0, early_exc_entry
csrw CSR_MTVEC, t0
/* Set the interrupt processing mode to ECLIC mode */
li t0, 0x3f
csrc CSR_MTVEC, t0
csrs CSR_MTVEC, 0x3
/* ===== Startup Stage 2 ===== */
/* Enable FPU and Vector Unit if f/d/v exist in march */
#if defined(__riscv_flen) && __riscv_flen > 0
/* Enable FPU, and set state to initial */
li t0, MSTATUS_FS
csrc mstatus, t0
li t0, MSTATUS_FS_INITIAL
csrs mstatus, t0
#endif
#if defined(__riscv_vector)
/* Enable Vector, and set state to initial */
li t0, MSTATUS_VS
csrc mstatus, t0
li t0, MSTATUS_VS_INITIAL
csrs mstatus, t0
#endif
/* Enable mcycle and minstret counter */
csrci CSR_MCOUNTINHIBIT, 0x5
call boot_run
/* Early boot exception entry before main */
.align 6
.global early_exc_entry
.type early_exc_entry, @function
early_exc_entry:
wfi
j early_exc_entry
.align 6
.global irq_entry
.type irq_entry, @function
irq_entry:
wfi
j irq_entry

View File

@@ -0,0 +1,151 @@
#include "chip.h"
#include "memap.h"
#include "PSRAMManager.h"
#include "ClockManager.h"
#include "boot_log.h"
#include <stdint.h>
extern uint32_t __scat_copy_base, __scat_copy_last, __scat_zero_base, __scat_zero_last;
extern uint32_t __psram_scat_copy_base, __psram_scat_copy_last, __psram_scat_zero_base, __psram_scat_zero_last;
typedef struct {
uint32_t len, *vma, *lma;
} scat_copy_item_t;
typedef struct {
uint32_t len, *vma;
} scat_zero_item_t;
static __attribute__((section(".init"))) void _scatload(uint32_t *dst, const uint32_t *src, uint32_t cnt)
{
while (cnt--) {
*dst++ = *src++;
}
}
static __attribute__((section(".init"))) void _scatfill(uint32_t *dst, uint32_t fill, int cnt)
{
while (cnt--) {
*dst++ = fill;
}
}
static __attribute__((section(".init"))) void scatload(void)
{
for (scat_copy_item_t *item = (void *)&__scat_copy_base; (uint32_t *)item < &__scat_copy_last; item++) {
if (item->vma && item->len >= sizeof(uint32_t) && item->vma != item->lma) {
_scatload(item->vma, item->lma, item->len >> 2);
}
}
for (scat_zero_item_t *item = (void *)&__scat_zero_base; (uint32_t *)item < &__scat_zero_last; item++) {
if (item->vma && item->len >= sizeof(uint32_t)) {
_scatfill(item->vma, 0, item->len >> 2);
}
}
}
static void scatload_psram(void)
{
for (scat_copy_item_t *item = (void *)&__psram_scat_copy_base; (uint32_t *)item < &__psram_scat_copy_last; item++) {
if (item->vma && item->len >= sizeof(uint32_t) && item->vma != item->lma) {
_scatload(item->vma, item->lma, item->len >> 2);
}
}
for (scat_zero_item_t *item = (void *)&__psram_scat_zero_base; (uint32_t *)item < &__psram_scat_zero_last; item++) {
if (item->vma && item->len >= sizeof(uint32_t)) {
_scatfill(item->vma, 0, item->len >> 2);
}
}
}
void irq_default_handler(void)
{
}
#define FALLBACK_DEFAULT_ECLIC_BASE 0x0C000000UL
#define FALLBACK_DEFAULT_SYSTIMER_BASE 0x02000000UL
volatile IRegion_Info_Type SystemIRegionInfo;
static void _get_iregion_info(volatile IRegion_Info_Type *iregion)
{
unsigned long mcfg_info;
if (iregion == NULL) {
return;
}
mcfg_info = __RV_CSR_READ(CSR_MCFG_INFO);
if (mcfg_info & MCFG_INFO_IREGION_EXIST) { // IRegion Info present
iregion->iregion_base = (__RV_CSR_READ(CSR_MIRGB_INFO) >> 10) << 10;
iregion->eclic_base = iregion->iregion_base + IREGION_ECLIC_OFS;
iregion->systimer_base = iregion->iregion_base + IREGION_TIMER_OFS;
iregion->smp_base = iregion->iregion_base + IREGION_SMP_OFS;
iregion->idu_base = iregion->iregion_base + IREGION_IDU_OFS;
} else {
iregion->eclic_base = FALLBACK_DEFAULT_ECLIC_BASE;
iregion->systimer_base = FALLBACK_DEFAULT_SYSTIMER_BASE;
}
}
static const uint32_t psram_size[] = {0, 32, 0, 64, 0, 128, 512, 256};
void boot_run(void)
{
__disable_irq();
scatload();
_get_iregion_info(&SystemIRegionInfo);
extern void BootClock_Init();
BootClock_Init();
__FENCE_I();
bootlog_init(CONFIG_BOOT_UART_PORT, CONFIG_BOOT_UART_BAUDRATE);
bootlog_dbg("main clk: %d Hz\n", CRM_GetSrcFreq(CRM_IpSrcCoreClk));
bootlog_dbg("psram clk: %d Hz\n", CRM_GetPsramFreq());
uint32_t rdly = 18, wdly = 22;
int r;
r = PSRAM_Initialize(&rdly, &wdly, 1);
if (r != 0) {
bootlog_err("psram error, code: %d\n", r);
while(1);
}
uint32_t density = ((IP_PSRAM_CTRL->REG_MR2.all & 0xff) >> 0) & 0x07;
if (density < sizeof(psram_size)/ sizeof(psram_size[0])) {
bootlog_dbg("psram inf, size: %d Mbit, w: %d, r: %d\n", psram_size[density], wdly, rdly);
} else {
bootlog_dbg("psram inf, size: unknown, w: %d, r: %d\n", wdly, rdly);
}
for (int i = 0; i < IRQ_MAX; i++) {
disable_IRQ(i);
clear_IRQ(i);
}
#if defined CONFIG_BOOT_CP_ENTRY
IP_CMN_SYS->REG_N300_CP_RST_ADDR.all = (uint32_t)CONFIG_BOOT_CP_ENTRY;
IP_SYSCTRL->REG_SW_RESET_CP0.all = 0xCAFE000A;
bootlog_dbg("cp: 0x%x\n", CONFIG_BOOT_CP_ENTRY);
#endif
#if defined CONFIG_BOOT_AP_ENTRY
if (CONFIG_BOOT_AP_ENTRY) {
void (*ap_core_start)(void) = (void (*)(void))CONFIG_BOOT_AP_ENTRY;
ap_core_start();
bootlog_dbg("ap: 0x%x\n", CONFIG_BOOT_AP_ENTRY);
}
#endif
bootlog_inf("ap: none\n");
while (1) {
__WFI();
}
}

View File

@@ -0,0 +1,258 @@
#include "stdint.h"
#include "log_print.h"
#include <stdio.h>
#include "uart_reg.h"
#include "chip.h"
#include "ClockManager.h"
#include "IOMuxManager.h"
static UART_RegDef *uart = NULL;
static uint32_t compute_gcd(uint32_t a, uint32_t c)
{
uint32_t t;
while (c != 0) {
t = a % c;
a = c;
c = t;
}
return a;
}
static int32_t __log_compute_div(int dbg, uint32_t baudrate, uint32_t *pm, uint32_t *pn, uint32_t div)
{
uint32_t gcd, m, n, tmp;
int32_t ret = 0;
tmp = div * baudrate;
uint32_t uart_clk;
if (dbg == 0) {
uart_clk = 24000000;
} else if (dbg == 1) {
uart_clk = 24000000;
}
gcd = compute_gcd(uart_clk, tmp);
m = uart_clk / gcd;
n = tmp / gcd;
if ((m > 1023) || (n > 511)) {
return -1;
}
*pm = m;
*pn = n;
return 0;
}
static int32_t log_compute_div(int dbg, uint32_t baudrate, uint32_t *pm, uint32_t *pn, uint32_t *pdiv)
{
int32_t ret = 0;
do {
if (__log_compute_div(dbg, baudrate, pm, pn, 4) == 0) {
*pdiv = 4;
break;
}
if (__log_compute_div(dbg, baudrate, pm, pn, 16) == 0) {
*pdiv = 16;
break;
}
ret = -1;
} while (0);
return ret;
}
#define CONFIG_SYSLOG_UART_TX_PIN 3
#define CONFIG_SYSLOG_UART_TX_PIN_FUNC_SEL 0x2
static void __log_io_config(int dbg)
{
IOMuxManager_PinConfigure(CSK_IOMUX_PAD_A, CONFIG_SYSLOG_UART_TX_PIN, CONFIG_SYSLOG_UART_TX_PIN_FUNC_SEL);
}
int syslog_write(const char *data, int len)
{
if (uart == NULL || data == NULL || len == 0) {
return 0;
}
for (int i = 0; i < len; i++) {
uart->REG_RXTX_BUFFER.all = data[i];
while (!uart->REG_STATUS.bit.TX_FIFO_SPACE)
;
}
return len;
}
int bootlog_init(int dbg, uint32_t baudrate)
{
uint32_t m, n, div, uart_base, cmn_reg;
if (log_compute_div(dbg, baudrate, &m, &n, &div) < 0) {
return -1;
}
__log_io_config(dbg);
switch (dbg) {
case 0:
uart = (UART_RegDef *)UART0_BASE;
__HAL_CRM_UART0_CLK_ENABLE();
HAL_CRM_SetUart0ClkDiv(n, m);
break;
case 1:
default:
uart = (UART_RegDef *)UART1_BASE;
__HAL_CRM_UART1_CLK_ENABLE();
HAL_CRM_SetUart1ClkDiv(n, m);
break;
}
uart->REG_IRQ_MASK.all = 0;
uart->REG_CTRL.all = 0;
if (div == 16) {
uart->REG_CTRL.bit.DIVISOR_MODE = 1; // 0: sclk/4; 1: sclk/16
} else {
uart->REG_CTRL.bit.DIVISOR_MODE = 0;
}
uart->REG_CMD_SET.bit.TX_FIFO_RESET = 1; // reset tx fifo
uart->REG_CMD_SET.bit.RX_FIFO_RESET = 1; // reset rx fifo
uart->REG_CTRL.bit.DATA_BITS = 1; // 8bits
uart->REG_CTRL.bit.ENABLE = 1; // enable uart
uart->REG_STATUS.all = 1; // clear line error bits
return 0;
}
static void int_to_str(int value, char *buf, size_t *written)
{
if (value < 0) {
buf[(*written)++] = '-';
value = -value;
}
if (value == 0) {
buf[(*written)++] = '0';
return;
}
char temp[10];
size_t index = 0;
while (value > 0) {
temp[index++] = (value % 10) + '0';
value /= 10;
}
for (size_t i = 0; i < index; i++) {
if (*written < 512 - 1) {
buf[(*written)++] = temp[index - 1 - i];
}
}
}
static void uint_to_hex_str(unsigned int value, char *buf, size_t *written)
{
if (value == 0) {
buf[(*written)++] = '0';
return;
}
char temp[8];
size_t index = 0;
while (value > 0) {
unsigned int digit = value % 16;
temp[index++] = (digit < 10) ? (digit + '0') : (digit - 10 + 'a');
value /= 16;
}
for (size_t i = 0; i < index; i++) {
if (*written < 512 - 1) {
buf[(*written)++] = temp[index - 1 - i];
}
}
}
int bootlog_vsnprintf(char *buf, size_t size, const char *format, va_list args)
{
size_t written = 0;
const char *p;
for (p = format; *p != '\0'; p++) {
if (*p != '%') {
if (written < size - 1) {
buf[written++] = *p;
}
continue;
}
p++;
switch (*p) {
case 'd': {
int value = va_arg(args, int);
int_to_str(value, buf, &written);
break;
}
case 'x': {
unsigned int value = va_arg(args, unsigned int);
uint_to_hex_str(value, buf, &written);
break;
}
case 's': {
const char *str = va_arg(args, const char *);
while (*str && written < size - 1) {
buf[written++] = *str++;
}
break;
}
default:
if (written < size - 1) {
buf[written++] = '%';
buf[written++] = *p;
}
break;
}
}
if (written < size) {
buf[written] = '\0';
} else if (size > 0) {
buf[size - 1] = '\0';
}
return written;
}
void bootlog_output(const char *format, va_list args)
{
static uint8_t buffer[512] = {0};
uint32_t len = bootlog_vsnprintf((char *)buffer, 512 - 1, format, args);
buffer[len] = '\0';
syslog_write(buffer, len);
}
int vprintk(const char *format, va_list args)
{
bootlog_output(format, args);
return 0;
}
int printk(const char *format, ...)
{
va_list args;
va_start(args, format);
vprintk(format, args);
va_end(args);
return 0;
}

View File

@@ -0,0 +1,66 @@
#ifndef __BOOT_LOG_H__
#define __BOOT_LOG_H__
int printk(const char *format, ...);
int bootlog_init(int dbg, uint32_t baudrate);
#define BOOTLOG_LVL_NON 0
#define BOOTLOG_LVL_ERR 1
#define BOOTLOG_LVL_WRN 2
#define BOOTLOG_LVL_INF 3
#define BOOTLOG_LVL_DBG 4
#if CONFIG_BOOT_LOG_LVL_NON
#define BOOTLOG_LVL BOOTLOG_LVL_NON
#elif CONFIG_BOOT_LOG_LVL_ERR
#define BOOTLOG_LVL BOOTLOG_LVL_ERR
#elif CONFIG_BOOT_LOG_LVL_WRN
#define BOOTLOG_LVL BOOTLOG_LVL_WRN
#elif CONFIG_BOOT_LOG_LVL_INF
#define BOOTLOG_LVL BOOTLOG_LVL_INF
#elif CONFIG_BOOT_LOG_LVL_DBG
#define BOOTLOG_LVL BOOTLOG_LVL_DBG
#endif
#ifndef BOOTLOG_LVL
#define BOOTLOG_LVL BOOTLOG_LVL_ERR
#endif
#if BOOTLOG_LVL >= BOOTLOG_LVL_ERR
#define bootlog_err(fmt, args...) \
do { \
printk("[boot] err: " fmt, ##args); \
} while (0)
#else
#define bootlog_err(fmt, args...)
#endif
#if BOOTLOG_LVL >= BOOTLOG_LVL_WRN
#define bootlog_wrn(fmt, args...) \
do { \
printk("[boot] wrn: " fmt, ##args); \
} while (0)
#else
#define bootlog_wrn(fmt, args...)
#endif
#if BOOTLOG_LVL >= BOOTLOG_LVL_INF
#define bootlog_inf(fmt, args...) \
do { \
printk("[boot] inf: " fmt, ##args); \
} while (0)
#else
#define bootlog_inf(fmt, args...)
#endif
#if BOOTLOG_LVL >= BOOTLOG_LVL_DBG
#define bootlog_dbg(fmt, args...) \
do { \
printk("[boot] dbg: " fmt, ##args); \
} while (0)
#else
#define bootlog_dbg(fmt, args...)
#endif
#endif

View File

@@ -0,0 +1,545 @@
/*
* cache_ap.c
*
* Created on: Jul 10, 2020
*
*/
#include <assert.h>
#include "chip.h"
#include "nmsis_core.h"
#include "cache.h"
/**
* @brief Enables the CPU instruction cache.
*
* This function activates the internal instruction cache of the CPU
* to enhance the execution speed of programs. It is part of the Hardware
* Abstraction Layer (HAL), providing an interface to manage hardware-specific
* features such as caching operations. Enabling the instruction cache allows
* for faster access to frequently executed instructions, which is crucial
* for performance-critical applications.
*/
void HAL_EnableICache(void){
#if HAL_ICACHE_VALID
__disable_irq();
EnableICache();
__enable_irq();
#endif
}
/**
* @brief Disables the CPU instruction cache.
*
* This function deactivates the internal instruction cache of the CPU
* to potentially aid in debugging or to meet specific system requirements
* where caching of instructions needs to be prevented. It is part of the Hardware
* Abstraction Layer (HAL), providing an interface to manage hardware-specific
* features such as caching operations. Disabling the instruction cache may be
* necessary in scenarios where precise control over instruction execution is required.
*/
void HAL_DisableICache(void){
#if HAL_ICACHE_VALID
__disable_irq();
DisableICache();
__enable_irq();
#endif
}
/**
* @brief Invalidates the CPU instruction cache.
*
* This function clears the contents of the internal instruction cache of the CPU.
* Invalidating the cache is useful to ensure that no stale or corrupted data is used
* by the CPU, which is particularly important after direct memory access (DMA) operations
* or after loading new programs into memory. It is part of the Hardware Abstraction Layer (HAL),
* providing an interface to manage hardware-specific features such as caching operations.
* This operation helps in maintaining data coherency and consistency across the system.
*/
void HAL_InvalidateICache(void){
#if HAL_ICACHE_VALID
__disable_irq();
MInvalICache();
__enable_irq();
#endif
}
/**
* @brief Invalidates a range of the CPU data cache based on address and size.
*
* This function clears a specific portion of the CPU's internal data cache. By providing
* an address and the size of the area, this function ensures that any modifications in
* memory in this specified range do not use stale or outdated cache entries. This is particularly
* useful for systems where memory regions are dynamically altered or when devices not supporting
* cache coherency modify the memory. It helps in maintaining data integrity and coherency
* especially in systems involving direct memory access (DMA) operations.
*
* @param addr Pointer to the start address of the memory region to invalidate.
* @param dsize Size of the memory region to invalidate, in bytes.
*/
void HAL_InvalidateICache_by_Addr(uint32_t *addr, uint32_t dsize){
#if HAL_ICACHE_VALID
__disable_irq();
unsigned long cnt = 0;
cnt = ((uint32_t)addr % HAL_ICACHE_CFG_LINE_SIZE + dsize + (HAL_ICACHE_CFG_LINE_SIZE - 1)) / HAL_ICACHE_CFG_LINE_SIZE;
MInvalICacheLines((unsigned long)addr, (unsigned long)cnt);
__enable_irq();
#endif
}
/**
* @brief Locks a range of the CPU instruction cache based on address and size.
*
* This function prevents the CPU instruction cache from being updated or invalidated within a specified
* range. It ensures that the cache entries in this range remain fixed and are not replaced or
* evicted. This can be useful in scenarios where instruction stability is critical and should not be
* changed by other operations or processes.
*
* @param addr Pointer to the start address of the memory region to lock.
* @param dsize Size of the memory region to lock, in bytes.
*/
void HAL_LockICache_by_Addr(uint32_t *addr, uint32_t dsize){
#if HAL_ICACHE_VALID
__disable_irq();
unsigned long cnt = 0;
cnt = ((uint32_t)addr % HAL_ICACHE_CFG_LINE_SIZE + dsize + (HAL_ICACHE_CFG_LINE_SIZE - 1)) / HAL_ICACHE_CFG_LINE_SIZE;
MLockICacheLines((unsigned long)addr, (unsigned long)cnt);
__enable_irq();
#endif
}
/**
* @brief Unlocks a previously locked range of the CPU instruction cache based on address and size.
*
* This function allows the CPU instruction cache to be updated or invalidated within a previously locked
* range. It ensures that the cache entries in this range can now be replaced or evicted as needed,
* returning the cache operation to its normal behavior. This is useful when the critical operation
* requiring instruction stability is complete and normal cache operations need to resume.
*
* @param addr Pointer to the start address of the memory region to unlock.
* @param dsize Size of the memory region to unlock, in bytes.
*/
void HAL_UnLockICache_by_Addr(uint32_t *addr, uint32_t dsize){
#if HAL_ICACHE_VALID
__disable_irq();
unsigned long cnt = 0;
cnt = ((uint32_t)addr % HAL_ICACHE_CFG_LINE_SIZE + dsize + (HAL_ICACHE_CFG_LINE_SIZE - 1)) / HAL_ICACHE_CFG_LINE_SIZE;
MUnlockICacheLines((unsigned long)addr, (unsigned long)cnt);
__enable_irq();
#endif
}
/**
* @brief Enables the CPU data cache.
*
* This function activates the internal data cache of the CPU
* to enhance the execution speed and efficiency of data access and processing.
* It is part of the Hardware Abstraction Layer (HAL), providing an interface to manage
* hardware-specific features such as caching operations. Enabling the data cache helps
* improve system performance by reducing memory access times and minimizing CPU idle time
* during data fetches from main memory.
*/
void HAL_EnableDCache(void){
#if HAL_DCACHE_VALID
__disable_irq();
EnableDCache();
__enable_irq();
#endif
}
/**
* @brief Disables the CPU data cache.
*
* This function deactivates the internal data cache of the CPU.
* Disabling the data cache can be useful in scenarios where data caching may lead
* to consistency issues, such as during non-cache-coherent DMA operations or when
* the predictability of every data access is required. It is part of the Hardware
* Abstraction Layer (HAL), providing an interface to manage hardware-specific features.
* Disabling the data cache ensures that all data reads and writes are directly made to
* and from the main memory, which can be crucial for real-time and safety-critical applications.
*/
void HAL_DisableDCache(void){
#if HAL_DCACHE_VALID
__disable_irq();
DisableDCache();
__enable_irq();
#endif
}
/**
* @brief Invalidates the CPU data cache.
*
* This function clears the contents of the internal data cache of the CPU.
* Invalidating the cache is essential to prevent the use of stale or incorrect data
* that might remain after changes in memory. It is commonly used after direct memory
* access (DMA) operations or when hardware devices modify memory outside of the CPU's control.
* It is part of the Hardware Abstraction Layer (HAL), providing an interface to manage
* hardware-specific features such as caching operations. This operation ensures data coherency
* and consistency across the system, particularly in systems where memory is shared between the CPU
* and other hardware components.
*/
void HAL_InvalidateDCache(void){
#if HAL_DCACHE_VALID
__disable_irq();
MInvalDCache();
__enable_irq();
#endif
}
/**
* @brief Flushes the CPU data cache.
*
* This function ensures that all modified data within the CPU's internal data cache
* are written back to the main memory. Flushing the data cache is crucial before
* any operations that require up-to-date data from other processors or hardware
* that do not have cache coherency mechanisms. It is part of the Hardware
* Abstraction Layer (HAL), providing an interface to manage hardware-specific features
* such as caching operations. This operation helps maintain data coherency and
* consistency across different parts of the system, particularly in multi-core
* or multi-processor environments.
*/
void HAL_FlushDCache(void){
#if HAL_DCACHE_VALID
__disable_irq();
MFlushDCache();
__enable_irq();
#endif
}
/**
* @brief Flushes and invalidates the CPU data cache.
*
* This function ensures that all modified data within the CPU's internal data cache
* are written back to the main memory, and then invalidates the cache to remove all entries.
* This is particularly useful in scenarios where data coherence and consistency are critical,
* such as before DMA operations where peripheral devices need to access the latest data,
* or after updating firmware that changes the memory layout. It is part of the Hardware
* Abstraction Layer (HAL), providing an interface to manage hardware-specific features
* such as caching operations. Flushing and invalidating the data cache ensures that
* no stale data is used and all future data reads are done directly from the main memory.
*/
void HAL_FlushInvalidateDCache(void){
#if HAL_DCACHE_VALID
__disable_irq();
MFlushInvalDCache();
__enable_irq();
#endif
}
/**
* @brief Invalidates a range of the CPU data cache based on address and size.
*
* This function clears a specific portion of the CPU's internal data cache. By providing
* an address and the size of the area, this function ensures that any modifications in
* memory in this specified range do not use stale or outdated cache entries. This is particularly
* useful for systems where memory regions are dynamically altered or when devices not supporting
* cache coherency modify the memory. It helps in maintaining data integrity and coherency
* especially in systems involving direct memory access (DMA) operations.
*
* @param addr Pointer to the start address of the memory region to invalidate.
* @param dsize Size of the memory region to invalidate, in bytes.
*/
void HAL_InvalidateDCache_by_Addr(uint32_t *addr, uint32_t dsize){
#if HAL_DCACHE_VALID
__disable_irq();
unsigned long cnt = 0;
cnt = ((uint32_t)addr % HAL_DCACHE_CFG_LINE_SIZE + dsize + (HAL_DCACHE_CFG_LINE_SIZE - 1)) / HAL_DCACHE_CFG_LINE_SIZE;
MInvalDCacheLines((unsigned long)addr, (unsigned long)cnt);
__enable_irq();
#endif
}
/**
* @brief Flushes a range of the CPU data cache based on address and size.
*
* This function writes back all modified data within a specified range of the CPU's internal data cache
* to the main memory. This operation is crucial for ensuring data coherence in systems where other processors
* or hardware devices access the same memory region but do not share a cache coherency mechanism. It is typically
* used prior to DMA operations or when processors in a multi-processor system access shared data.
*
* @param addr Pointer to the start address of the memory region to flush.
* @param dsize Size of the memory region to flush, in bytes.
*/
void HAL_FlushDCache_by_Addr(uint32_t *addr, uint32_t dsize){
#if HAL_DCACHE_VALID
__disable_irq();
unsigned long cnt = 0;
cnt = ((uint32_t)addr % HAL_DCACHE_CFG_LINE_SIZE + dsize + (HAL_DCACHE_CFG_LINE_SIZE - 1)) / HAL_DCACHE_CFG_LINE_SIZE;
MFlushDCacheLines((unsigned long)addr, (unsigned long)cnt);
__enable_irq();
#endif
}
/**
* @brief Flushes and invalidates a range of the CPU data cache based on address and size.
*
* This function combines the actions of writing back all modified data within a specified range
* of the CPU's internal data cache to the main memory and then invalidating the cache entries.
* This ensures that no stale data remains and all future accesses to this memory range will be
* fetched directly from the main memory. This operation is particularly vital in systems with
* non-cache-coherent DMA operations or in multi-core systems where processors need to share
* up-to-date data without any inconsistencies.
*
* @param addr Pointer to the start address of the memory region to flush and invalidate.
* @param dsize Size of the memory region to flush and invalidate, in bytes.
*/
void HAL_FlushInvalidateDCache_by_Addr(uint32_t *addr, uint32_t dsize){
#if HAL_DCACHE_VALID
__disable_irq();
unsigned long cnt = 0;
cnt = ((uint32_t)addr % HAL_DCACHE_CFG_LINE_SIZE + dsize + (HAL_DCACHE_CFG_LINE_SIZE - 1)) / HAL_DCACHE_CFG_LINE_SIZE;
MFlushInvalDCacheLines((unsigned long)addr, (unsigned long)cnt);
__enable_irq();
#endif
}
/**
* @brief Locks a range of the CPU data cache based on address and size.
*
* This function prevents the CPU data cache from being updated or invalidated within a specified
* range. It ensures that the cache entries in this range remain fixed and are not replaced or
* evicted. This can be useful in scenarios where data stability is critical and should not be
* changed by other operations or processes.
*
* @param addr Pointer to the start address of the memory region to lock.
* @param dsize Size of the memory region to lock, in bytes.
*/
void HAL_LockDCache_by_Addr(uint32_t *addr, uint32_t dsize){
#if HAL_DCACHE_VALID
__disable_irq();
unsigned long cnt = 0;
cnt = ((uint32_t)addr % HAL_DCACHE_CFG_LINE_SIZE + dsize + (HAL_DCACHE_CFG_LINE_SIZE - 1)) / HAL_DCACHE_CFG_LINE_SIZE;
MLockDCacheLines((unsigned long)addr, (unsigned long)cnt);
__enable_irq();
#endif
}
/**
* @brief Unlocks a previously locked range of the CPU data cache based on address and size.
*
* This function allows the CPU data cache to be updated or invalidated within a previously locked
* range. It ensures that the cache entries in this range can now be replaced or evicted as needed,
* returning the cache operation to its normal behavior. This is useful when the critical operation
* requiring data stability is complete and normal cache operations need to resume.
*
* @param addr Pointer to the start address of the memory region to unlock.
* @param dsize Size of the memory region to unlock, in bytes.
*/
void HAL_UnLockDCache_by_Addr(uint32_t *addr, uint32_t dsize){
#if HAL_DCACHE_VALID
__disable_irq();
unsigned long cnt = 0;
cnt = ((uint32_t)addr % HAL_DCACHE_CFG_LINE_SIZE + dsize + (HAL_DCACHE_CFG_LINE_SIZE - 1)) / HAL_DCACHE_CFG_LINE_SIZE;
MUnlockDCacheLines((unsigned long)addr, (unsigned long)cnt);
__enable_irq();
#endif
}
// This function will be abandon
int range_is_cacheable(unsigned long start, unsigned long size){
return 0;
}
void unaligned_cache_line_move(unsigned char* src, unsigned char* dst, unsigned long len)
{
__disable_irq();
int i;
unsigned char* src_p = (unsigned char*) src;
unsigned char* dst_p = (unsigned char*) dst;
for (i = 0; i < len; ++i) {
*(dst_p + i) = *(src_p + i);
}
__enable_irq();
}
void dcache_clean_range(unsigned long start, unsigned long end){
uint32_t line_mask = HAL_DCACHE_CFG_LINE_SIZE - 1;
// 对start向上取整到cache line边界
unsigned long aligned_start = (start + line_mask) & (~line_mask);
// 对end向下取整到cache line边界
unsigned long aligned_end = end & (~line_mask);
__disable_irq();
// 只有当有完整的cache line需要处理时才进行操作
if (aligned_start < aligned_end) {
HAL_FlushDCache_by_Addr((uint32_t *)aligned_start, (aligned_end - aligned_start));
}
// 对不对齐的部分进行单独处理
if (start < aligned_start) {
// 处理start到aligned_start之间的数据
// 这里需要更细粒度的处理方式
}
if (end > aligned_end) {
// 处理aligned_end到end之间的数据
// 这里需要更细粒度的处理方式
}
__enable_irq();
}
void dcache_invalidate_range(unsigned long start, unsigned long end){
uint32_t line_mask = HAL_DCACHE_CFG_LINE_SIZE - 1;
// 对start向上取整到cache line边界
unsigned long aligned_start = (start + line_mask) & (~line_mask);
// 对end向下取整到cache line边界
unsigned long aligned_end = end & (~line_mask);
__disable_irq();
// 只有当有完整的cache line需要处理时才进行操作
if (aligned_start < aligned_end) {
HAL_InvalidateDCache_by_Addr((uint32_t *)aligned_start, (aligned_end - aligned_start));
}
// 对不对齐的部分进行单独处理
if (start < aligned_start) {
// 处理start到aligned_start之间的数据
// 这里需要更细粒度的处理方式
}
if (end > aligned_end) {
// 处理aligned_end到end之间的数据
// 这里需要更细粒度的处理方式
}
__enable_irq();
}
void dcache_flush_range(unsigned long start, unsigned long end){
uint32_t line_mask = HAL_DCACHE_CFG_LINE_SIZE - 1;
// 对start向上取整到cache line边界
unsigned long aligned_start = (start + line_mask) & (~line_mask);
// 对end向下取整到cache line边界
unsigned long aligned_end = end & (~line_mask);
__disable_irq();
// 只有当有完整的cache line需要处理时才进行操作
if (aligned_start < aligned_end) {
HAL_FlushDCache_by_Addr((uint32_t *)aligned_start, (aligned_end - aligned_start));
HAL_InvalidateDCache_by_Addr((uint32_t *)aligned_start, (aligned_end - aligned_start));
}
// 对不对齐的部分进行单独处理
if (start < aligned_start) {
// 处理start到aligned_start之间的数据
// 这里需要更细粒度的处理方式
}
if (end > aligned_end) {
// 处理aligned_end到end之间的数据
// 这里需要更细粒度的处理方式
}
__enable_irq();
}
void cache_dma_fast_inv_stage1(unsigned long start, unsigned long end){
unsigned long line_size;
unsigned long old_start = start;
unsigned long old_end = end;
line_size = HAL_DCACHE_CFG_LINE_SIZE;
start = start & (~(line_size - 1));
end = (end + line_size - 1) & (~(line_size - 1));
if (start == end)
return;
__disable_irq();
if (start != old_start) {
HAL_FlushDCache_by_Addr((uint32_t *)start, line_size);
}
if (end != old_end) {
HAL_FlushDCache_by_Addr((uint32_t *)(end - line_size), line_size);
}
HAL_InvalidateDCache_by_Addr((uint32_t *)start, (end - start));
__enable_irq();
}
// void cache_dma_fast_inv_stage2(unsigned long start, unsigned long end){
// }
// dcache_clean_range(buff_addr, buff_addr + blk_sz * blk_cnt);
// gm_cpu_clean_dcache_range(q->payload, q->len);
// gm_cpu_dcache_invalidate_range(q->payload, q->len);
// cache_dma_fast_inv_stage1(buff_addr, buff_addr + blk_sz * blk_cnt);
// dcache_clean_range(buff_addr, buff_addr + blk_sz * blk_cnt);
// // usually called after transferring data to memory (NOT cache-line-aligned) via DMA
void cache_dma_fast_inv_stage2(unsigned long start, unsigned long end)
{
unsigned long line_size;
unsigned long old_start = start;
unsigned long old_end = end;
static unsigned char cache_line_buf[32];
line_size = HAL_DCACHE_CFG_LINE_SIZE;
start = start & (~(line_size - 1));
end = (end + line_size - 1) & (~(line_size - 1));
if (start == end)
return;
int use_lock = 0;
// interrupt enabled, and not in interrupt context
if(start != old_start || end != old_end)
use_lock = 1;
if (use_lock) {
disable_GINT();
}
__disable_irq();
if (start != old_start) {
unaligned_cache_line_move((unsigned char*) start, cache_line_buf, old_start - start);
HAL_InvalidateDCache_by_Addr((uint32_t *)start, line_size);
unaligned_cache_line_move(cache_line_buf, (unsigned char*) start, old_start - start);
}
if (end != old_end) {
unaligned_cache_line_move((unsigned char*) old_end, cache_line_buf, end - old_end);
HAL_InvalidateDCache_by_Addr((uint32_t *)(end - line_size), line_size);
unaligned_cache_line_move(cache_line_buf, (unsigned char*) old_end, end - old_end);
}
__enable_irq();
if (use_lock) {
enable_GINT();
}
}

View File

@@ -0,0 +1,516 @@
/*
* Copyright (c) 2019 Nuclei Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* 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.
*/
/******************************************************************************
* @file gcc_evalsoc_ilm.ld
* @brief GNU Linker Script for Nuclei N/NX based device
* @version V1.0.0
* @date 17. Dec 2019
******************************************************************************/
OUTPUT_ARCH("riscv")
ENTRY(_start)
////////////////////////////////////////////////////////////////////////////////
/*
* R - Read-only sections.
* W - Read/write sections.
* X - Sections containing executable code.
* A - Allocated sections.
* I/L - Initialized sections.
* ! - Invert the sense of any of the following attributes.
*/
#include "memap.h"
MEMORY {
PSRAM(rwxa ) : ORIGIN = MEM_PSRAM_BASE, LENGTH = MEM_PSRAM_SIZE
FLASH(rxa!w) : ORIGIN = MEM_FLASH_BASE, LENGTH = MEM_FLASH_SIZE
SRAM(rwxa ) : ORIGIN = MEM_SRAM_BASE, LENGTH = MEM_SRAM_SIZE
ILM(rwx ) : ORIGIN = MEM_ILM_BASE, LENGTH = MEM_ILM_SIZE
DLM(rw ) : ORIGIN = MEM_DLM_BASE, LENGTH = MEM_DLM_SIZE
#if defined(MEM_IPC_BASE)
/* 共享内存 */
IPC_RAM(rwx) : ORIGIN = MEM_IPC_BASE, LENGTH = MEM_IPC_SIZE
#endif
#if defined(MEM_WFRAM_BASE)
/* 这段内存预留给WIFI使用 */
WIFI_RAM (rwx) : ORIGIN = MEM_WFRAM_BASE, LENGTH = MEM_WFRAM_SIZE
#endif
}
REGION_ALIAS("ITCM", ILM)
REGION_ALIAS("DTCM", DLM)
REGION_ALIAS("ROM", FLASH)
REGION_ALIAS("RAM", SRAM)
/* 如果不定义 MEM_WFRAM_BASE 的话, wifi ram从sram中分配 */
#if !defined(MEM_WFRAM_BASE)
REGION_ALIAS("WIFI_RAM", SRAM)
#endif
/* 如果不定义 MEM_IPC_BASE 的话, ipc shared ram从sram中分配 */
#if !defined(MEM_IPC_BASE)
REGION_ALIAS("IPC_RAM", SRAM)
#endif
#define SCATCOPY(LEN,VMA,LMA) LONG(LEN) LONG(VMA) LONG(LMA)
#define SCATLOAD(SCT) LONG(SIZEOF(SCT)) LONG(ADDR(SCT)) LONG(LOADADDR(SCT))
#define SCATZERO(SCT) LONG(SIZEOF(SCT)) LONG(ADDR(SCT))
SECTIONS {
PROVIDE(__STACK_SIZE = MEM_INTERRUPT_STACK_SIZE);
PROVIDE(__HEAP_SIZE = 512);
/* wifi 校准数据预留大小 */
PROVIDE(_lcali = MEM_WIFI_CALIBRATION_SIZE);
/* wifi 跟踪数据预留大小 */
PROVIDE(_trace_len = MEM_WIFI_TRACE_SIZE);
/* 优先将这个段放在前面, 确保wifi ram自动从sram分配时, 前面的地址给wifi使用 */
.wifi.noinit (NOLOAD):
{
. = ALIGN(4);
_wifi_ram_start = . ;
#if CONFIG_WIFI_CALI_BUF
_scali = .;
. += _lcali;
_ecali = .;
#endif
_trace_start = .;
. += _trace_len;
_trace_end = .;
_sshram = . ;
*(SHAREDRAMIPC)
*(SHAREDRAM)
_eshram = . ;
. = ALIGN(4);
_wifi_ram_end = . ;
} > WIFI_RAM
/* WIFI外设只能访问 0x20000000 - 0x20000000 + 256 * 1024这段内存 */
ASSERT ((_wifi_ram_start >= (0x20000000)), "error: wifi ram start must be greater than 0x20000000")
ASSERT ((_wifi_ram_end <= (0x20000000 + 256 * 1024)), "error: wifi ram end must be less than 0x20000000 + 256 * 1024")
.init : {
/* Default Vector Table */
. = ALIGN(4);
PROVIDE(_rom_code_start = .);
* (.vtable)
* (.init)
/* Starup Initialition Region */
. = ALIGN(4);
PROVIDE(_rom_code_end = .);
} >ROM AT>ROM
.scatab : ALIGN(4) {
/* Prev Scatter Copy/Load Table */
. = ALIGN(4);
PROVIDE(__scat_copy_base = .);
SCATLOAD(.itcm);
SCATLOAD(.dtcm);
SCATLOAD(.fast.text);
SCATLOAD(.fast.rodata);
SCATLOAD(.fast.data);
SCATLOAD(.text);
SCATLOAD(.rodata);
SCATLOAD(.data);
SCATLOAD(.shell);
SCATLOAD(.mapi);
PROVIDE(__scat_copy_last = .);
/* Scatter Zero-Fill Table */
. = ALIGN(4);
PROVIDE(__scat_zero_base = .);
SCATZERO(.dtcm.bss);
SCATZERO(.fast.bss);
SCATZERO(.bss);
PROVIDE(__scat_zero_last = .);
. = ALIGN(4);
} >ROM AT>ROM
.psram_scatab : ALIGN(4) {
/* Prev Scatter Copy/Load Table */
. = ALIGN(4);
PROVIDE(__psram_scat_copy_base = .);
SCATLOAD(.psram.text);
SCATLOAD(.psram.data);
SCATLOAD(.psram.rodata);
PROVIDE(__psram_scat_copy_last = .);
/* Scatter Zero-Fill Table */
. = ALIGN(4);
PROVIDE(__psram_scat_zero_base = .);
SCATZERO(.psram.bss);
PROVIDE(__psram_scat_zero_last = .);
. = ALIGN(4);
} >ROM AT>ROM
.psram.data : ALIGN(4) {
. = ALIGN(4);
PROVIDE(__psram_data_start = .);
* (.psram.data)
* (.psram.data.*)
*psram*.a: (.data .data.*)
. = ALIGN(4);
PROVIDE(__psram_data_end = .);
} >PSRAM AT>ROM
.psram.bss(NOLOAD): ALIGN(4) {
. = ALIGN(4);
PROVIDE(__psram_bss_start = .);
* (.psram.bss)
* (.psram.bss.*)
*psram*.a: (.sbss .sbss.* .bss .bss.*)
. = ALIGN(4);
PROVIDE(__psram_bss_end = .);
} >PSRAM
.psram.noinit(NOLOAD) : ALIGN(4) {
. = ALIGN(4);
PROVIDE(__psram_noinit_start = .);
* (.psram.noinit)
* (.psram.noinit.*)
*psram*.a: (.noinit .noinit.*)
. = ALIGN(4);
PROVIDE(__psram_noinit_end = .);
} >PSRAM
////////////////////////////////////////////////////////////////////////////
// ROM/RAM => FAST/RAM
.fast.text : ALIGN(4) {
. = ALIGN(4);
PROVIDE(_ram_code_start = .);
* (.ramcode)
* (.text.irq .text.xPortTaskSwitch .text.eclic_mtip_handler)
* (.fast_text .fast_text.*)
/* *heap.a: (.text .text.*) */
*mapi.o (.text .text.*)
PROVIDE(_ram_code_end = .);
. = ALIGN(4);
} >SRAM AT>ROM
.itcm : ALIGN(4) {
. = ALIGN(4);
PROVIDE(_itcm_code_start = .);
* (.itcm_text .itcm_text.* .itcm*)
PROVIDE(_itcm_code_end = .);
. = ALIGN(4);
} >ITCM AT>ROM
.dtcm : ALIGN(4) {
. = ALIGN(4);
* (.dtcm .dtcm.*)
. = ALIGN(4);
} >DTCM AT>ROM
.dtcm.bss (NOLOAD) : ALIGN(4) {
. = ALIGN(4);
* (.dtcm.bss .dtcm.bss*)
. = ALIGN(4);
} >DTCM
.fast.rodata : ALIGN(4) {
. = ALIGN(4);
* (.fast_rodata .fast_rodata.*)
*heap.a: (.rodata .rodata.*)
. = ALIGN(4);
} >RAM AT>ROM
.fast.data : ALIGN(4) {
. = ALIGN(4);
* (.fast_data .fast_data.*)
*heap.a: (.data .data.*)
. = ALIGN(4);
} >RAM AT>ROM
.fast.bss(NOLOAD) : ALIGN(4) {
. = ALIGN(4);
* (.fast_bss .fast_bss.*)
*heap.a: (.bss .bss.*)
. = ALIGN(4);
} >RAM AT>RAM
////////////////////////////////////////////////////////////////////////////
// ROM => ROM
.shell : ALIGN(4) {
. = ALIGN(4);
_shell_items_start = .;
KEEP(* (.shell.user))
KEEP(* (.shell.priv))
. = ALIGN(4);
} >ROM AT>ROM
.shell_command :
{
_shell_command_start = .;
KEEP (*(shellCommand))
_shell_command_end = .;
} >ROM AT>ROM
.psram.text : ALIGN(4) {
. = ALIGN(4);
PROVIDE(__psram_text_start = .);
* (.psram.text)
* (.psram.text.*)
*libmodules_lvgl.a:*(.text .text.* .stext .stext.*)
. = ALIGN(4);
PROVIDE(__psram_text_end = .);
} >PSRAM AT>ROM
.text : ALIGN(4) {
. = ALIGN(4);
PROVIDE(_rom_code2_start = .);
* (.stext .stext.*)
* (.text .text.*)
* (.gnu.linkonce.t.*)
. = ALIGN(4);
PROVIDE(_rom_code2_end = .);
} >ROM AT>ROM
#if CONFIG_LINK_CPP_RUNTIME_SECTIONS
.fini :
{
KEEP (*(SORT_NONE(.fini)))
} >ROM AT>ROM
.preinit_array :
{
PROVIDE_HIDDEN (__preinit_array_start = .);
KEEP (*(.preinit_array))
PROVIDE_HIDDEN (__preinit_array_end = .);
} >ROM AT>ROM
.init_array :
{
PROVIDE_HIDDEN (__init_array_start = .);
KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))
KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors))
PROVIDE_HIDDEN (__init_array_end = .);
} >ROM AT>ROM
.fini_array :
{
PROVIDE_HIDDEN (__fini_array_start = .);
KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))
KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors))
PROVIDE_HIDDEN (__fini_array_end = .);
} >ROM AT>ROM
.ctors :
{
/* gcc uses crtbegin.o to find the start of
* the constructors, so we make sure it is
* first. Because this is a wildcard, it
* doesn't matter if the user does not
* actually link against crtbegin.o; the
* linker won't look for a file to match a
* wildcard. The wildcard also means that it
* doesn't matter which directory crtbegin.o
* is in.
*/
KEEP (*crtbegin.o(.ctors))
KEEP (*crtbegin?.o(.ctors))
/* We don't want to include the .ctor section from
* the crtend.o file until after the sorted ctors.
* The .ctor section from the crtend file contains the
* end of ctors marker and it must be last
*/
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*(.ctors))
} >ROM AT>ROM
.dtors :
{
KEEP (*crtbegin.o(.dtors))
KEEP (*crtbegin?.o(.dtors))
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*(.dtors))
} >ROM AT>ROM
/* C++ 异常处理支持 */
.eh_frame_hdr :
{
*(.eh_frame_hdr)
*(.eh_frame_entry .eh_frame_entry.*)
} >ROM AT>ROM
.eh_frame :
{
. = ALIGN(4);
PROVIDE(__eh_frame = .);
KEEP(*(.eh_frame))
/**
* As we are not linking with crtend.o, which includes the CIE terminator
* (see __FRAME_END__ in libgcc sources), it is manually provided here.
*/
LONG(0)
} >ROM AT>ROM
.gcc_except_table :
{
*(.gcc_except_table .gcc_except_table.*)
} >ROM AT>ROM
/* C++ 标准库静态数据 */
.rodata.cst4 :
{
*(.rodata.cst4)
} >ROM AT>ROM
.rodata.cst8 :
{
*(.rodata.cst8)
} >ROM AT>ROM
#endif // CONFIG_LINK_OPTION_NONE_SPECS
.psram.rodata : ALIGN(4) {
. = ALIGN(4);
* (.psram.rodata)
* (.psram.rodata.*)
. = ALIGN(4);
} >PSRAM AT>ROM
.rodata : ALIGN(4) {
. = ALIGN(4);
* (.rodata .rodata.*)
* (.strdat)
. = ALIGN(4);
} >ROM AT>ROM
.lisaui_apps : {
. = ALIGN(4);
__lisaui_apps_start = .;
KEEP (*(.lisaui*))
. = ALIGN(4);
__lisaui_apps_end = .;
} >ROM AT>ROM
////////////////////////////////////////////////////////////////////////////
// ROM => RAM
.mapi : ALIGN(4) {
. = ALIGN(4);
PROVIDE_HIDDEN(__mod_stdc = .);
KEEP(* (SORT(.mod.0.*)))
PROVIDE_HIDDEN(__mod_rtos = .);
KEEP(* (SORT(.mod.?.*)))
PROVIDE_HIDDEN(__mod_ends = .);
. = ALIGN(4);
} >RAM AT>ROM
.trace : ALIGN(4) {
. = ALIGN(4);
_trace_start = .;
KEEP(*(TRACE))
_trace_end = .;
. = ALIGN(4);
} >RAM AT>ROM
.data : ALIGN(8) {
. = ALIGN(8);
* (.data .data.*)
* (.gnu.linkonce.d.*)
. = ALIGN(8);
PROVIDE(__global_pointer$ = . + 0x800);
* (.sdata .sdata.*)
* (.gnu.linkonce.s.*)
. = ALIGN(8);
* (.rdata .rdata.*)
* (.gnu.linkonce.r.*)
* (.srodata .srodata.*)
} >RAM AT>ROM
#if defined(MEM_IPC_BASE)
/* ipc shared RAM */
.ipc.shared (NOLOAD):
{
_ipcshram = . ;
*(SHAREDRAM_AMP_IPC_ENV)
*(SHAREDRAM_AMP_IPC)
*(SORT(.ipc.*))
_eipcshram = . ;
} > IPC_RAM
#endif
PROVIDE(__tls_base = .);
.psram.nocache_heap ORIGIN(PSRAM) (NOLOAD):{
. = ALIGN(0x100000);
PROVIDE(__psram_nocache_heap_start = .);
* (.psram.nocache_heap)
. = ALIGN(4);
PROVIDE(__psram_nocache_heap_end = .);
} >PSRAM
////////////////////////////////////////////////////////////////////////////
// ZERO => RAM
.bss(NOLOAD) : ALIGN(8) {
. = ALIGN(8);
* (.sbss .sbss.*)
* (.gnu.linkonce.sb.*)
* (.bss .bss.*)
* (.gnu.linkonce.b.*)
* (COMMON)
. = ALIGN(4);
} >RAM AT>RAM
.noinit (NOLOAD): ALIGN(4) {
. = ALIGN(4);
* (.noinit)
* (.noinit.*)
. = ALIGN(4);
} >RAM
////////////////////////////////////////////////////////////////////////////
// ROM => ROM
.stub : {
KEEP (* (.stub))
} >ROM AT>ROM
PROVIDE( _end = . );
PROVIDE( end = . );
////////////////////////////////////////////////////////////////////////////
///* RTOS Heap Region (8 bytes aligned at least) */
//.rtosheap(NOLOAD) : ALIGN(16) {
// . = ALIGN(ORIGIN(RAM) + LENGTH(RAM) - __HEAP_SIZE - __STACK_SIZE, 16);
//} >RAM AT>RAM
//PROVIDE(__vmaof_osheap = ADDR(.rtosheap));
//PROVIDE(__lenof_osheap = SIZEOF(.rtosheap));
/* Nuclei C Runtime Library requirements:
* 1. heap need to be align at 16 bytes
* 2. __heap_start and __heap_end symbol need to be defined
* 3. reserved at least __HEAP_SIZE space for heap
* 4. reserved at least __STACK_SIZE space for stack */
.heapstack(NOLOAD) : ALIGN(16) {
. = ALIGN(16);
PROVIDE(__heap_start = .);
. += __HEAP_SIZE;
. = ALIGN(16);
PROVIDE(__heap_end = .);
PROVIDE(_sstack = .);
PROVIDE(__StackLimit = .);
. += __STACK_SIZE;
. = ALIGN(16);
PROVIDE(__StackTop = .);
PROVIDE(_estack = .);
} >RAM AT>RAM
}

View File

@@ -0,0 +1,32 @@
#ifndef __ARCS_MEMAP_HEADER__
#define __ARCS_MEMAP_HEADER__
#define MEM_SRAM_BASE 0x20050000
#define MEM_SRAM_SIZE (384 * 1024)
#define MEM_PSRAM_BASE 0x28000000
#define MEM_PSRAM_SIZE (16 * 1024 * 1024)
#ifndef CONFIG_BOOT_FLASH_SIZE
#warning "BOOT_FLASH_SIZE is not defined"
#define CONFIG_BOOT_FLASH_SIZE (8 * 1024)
#endif
#define MEM_FLASH_BASE (CONFIG_MEM_FLASH_BASE)
#define MEM_FLASH_SIZE (CONFIG_BOOT_FLASH_SIZE)
#define MEM_WFRAM_BASE 0x20000000
#define MEM_WFRAM_SIZE (256 * 1024)
#define MEM_ILM_BASE 0x00080000
#define MEM_ILM_SIZE (16 * 1024)
#define MEM_DLM_BASE 0x00100000
#define MEM_DLM_SIZE (8 * 1024)
#define MEM_WIFI_CALIBRATION_SIZE (16 * 1024)
#define MEM_WIFI_TRACE_SIZE (8 * 1024)
#define MEM_INTERRUPT_STACK_SIZE (4 * 1024)
#endif