Remove heap related symbols, use all remaining memory for the stack (#716)
* Use all remaining memory for stack(s) * Remove HEAP related code from RISCV linker scripts * Fix direct-boot / mcu-boot linker scripts * Use a statically allocated stack for core-1
This commit is contained in:
parent
659cdffcba
commit
92bda00296
@ -42,6 +42,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
- Update `embedded-hal-*` alpha packages to their latest versions (#640)
|
||||
- Implement the `Clone` and `Copy` traits for the `Rng` driver (#650)
|
||||
- Use all remaining memory as core-0's stack (#716)
|
||||
|
||||
### Fixed
|
||||
|
||||
|
||||
@ -39,7 +39,7 @@ embassy-time = { version = "0.1.2", features = ["nightly"], optional = tru
|
||||
embassy-futures = { version = "0.1.0", optional = true }
|
||||
|
||||
# RISC-V
|
||||
esp-riscv-rt = { version = "0.4.0", path = "../esp-riscv-rt", optional = true }
|
||||
esp-riscv-rt = { version = "0.5.0", path = "../esp-riscv-rt", optional = true }
|
||||
riscv-atomic-emulation-trap = { version = "0.4.0", optional = true }
|
||||
|
||||
# Xtensa
|
||||
|
||||
@ -10,9 +10,6 @@ ERROR(riscv-rt): the start of the RODATA must be 4-byte aligned");
|
||||
ASSERT(ORIGIN(REGION_DATA) % 4 == 0, "
|
||||
ERROR(riscv-rt): the start of the REGION_DATA must be 4-byte aligned");
|
||||
|
||||
ASSERT(ORIGIN(REGION_HEAP) % 4 == 0, "
|
||||
ERROR(riscv-rt): the start of the REGION_HEAP must be 4-byte aligned");
|
||||
|
||||
ASSERT(ORIGIN(ROTEXT) % 4 == 0, "
|
||||
ERROR(riscv-rt): the start of the ROTEXT must be 4-byte aligned");
|
||||
|
||||
@ -31,17 +28,10 @@ BUG(riscv-rt): the LMA of .data is not 4-byte aligned");
|
||||
ASSERT(_bss_start % 4 == 0 && _bss_end % 4 == 0, "
|
||||
BUG(riscv-rt): .bss is not 4-byte aligned");
|
||||
|
||||
ASSERT(_sheap % 4 == 0, "
|
||||
BUG(riscv-rt): start of .heap is not 4-byte aligned");
|
||||
|
||||
ASSERT(_stext + SIZEOF(.text) < ORIGIN(ROTEXT) + LENGTH(ROTEXT), "
|
||||
ERROR(riscv-rt): The .text section must be placed inside the ROTEXT region.
|
||||
Set _stext to an address smaller than 'ORIGIN(ROTEXT) + LENGTH(ROTEXT)'");
|
||||
|
||||
ASSERT(SIZEOF(.stack) > (_max_hart_id + 1) * _hart_stack_size, "
|
||||
ERROR(riscv-rt): .stack section is too small for allocating stacks for all the harts.
|
||||
Consider changing `_max_hart_id` or `_hart_stack_size`.");
|
||||
|
||||
ASSERT(SIZEOF(.got) == 0, "
|
||||
.got section detected in the input files. Dynamic relocations are not
|
||||
supported. If you are linking to C code compiled using the `gcc` crate
|
||||
|
||||
@ -1,35 +0,0 @@
|
||||
|
||||
|
||||
SECTIONS {
|
||||
.external.data :
|
||||
{
|
||||
_external_data_start = ABSOLUTE(.);
|
||||
. = ALIGN(4);
|
||||
*(.external.data .external.data.*)
|
||||
_external_data_end = ABSOLUTE(.);
|
||||
} > psram_seg AT > RODATA
|
||||
|
||||
.external.bss (NOLOAD) :
|
||||
{
|
||||
_external_bss_start = ABSOLUTE(.);
|
||||
. = ALIGN(4);
|
||||
*(.external.bss .external.bss.*)
|
||||
_external_bss_end = ABSOLUTE(.);
|
||||
} > psram_seg
|
||||
|
||||
.external.noinit (NOLOAD) :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
*(.external.noinit .external.noinit.*)
|
||||
} > psram_seg
|
||||
|
||||
/* must be last segment using psram_seg */
|
||||
.external_heap_start (NOLOAD) :
|
||||
{
|
||||
. = ALIGN (4);
|
||||
_external_heap_start = ABSOLUTE(.);
|
||||
} > psram_seg
|
||||
}
|
||||
|
||||
_external_ram_start = ABSOLUTE(ORIGIN(psram_seg));
|
||||
_external_ram_end = ABSOLUTE(ORIGIN(psram_seg)+LENGTH(psram_seg));
|
||||
@ -51,9 +51,9 @@ SECTIONS {
|
||||
} > RWDATA AT > RODATA
|
||||
|
||||
/* must be last segment using RWDATA */
|
||||
.heap_start (NOLOAD) : ALIGN(4)
|
||||
.stack_end (NOLOAD) : ALIGN(4)
|
||||
{
|
||||
. = ALIGN (4);
|
||||
_heap_start = ABSOLUTE(.);
|
||||
_stack_end = ABSOLUTE(.);
|
||||
} > RWDATA
|
||||
}
|
||||
@ -15,13 +15,17 @@
|
||||
//!
|
||||
//! ## Example
|
||||
//! ```no_run
|
||||
//! static mut APP_CORE_STACK: Stack<8192> = Stack::new();
|
||||
//!
|
||||
//! let counter = Mutex::new(RefCell::new(0));
|
||||
//!
|
||||
//! let mut cpu_control = CpuControl::new(system.cpu_control);
|
||||
//! let mut cpu1_fnctn = || {
|
||||
//! cpu1_task(&mut timer1, &counter);
|
||||
//! };
|
||||
//! let _guard = cpu_control.start_app_core(&mut cpu1_fnctn).unwrap();
|
||||
//! let _guard = cpu_control
|
||||
//! .start_app_core(unsafe { &mut APP_CORE_STACK }, &mut cpu1_fnctn)
|
||||
//! .unwrap();
|
||||
//!
|
||||
//! loop {
|
||||
//! block!(timer0.wait()).unwrap();
|
||||
@ -55,8 +59,24 @@ use xtensa_lx::set_stack_pointer;
|
||||
|
||||
use crate::Cpu;
|
||||
|
||||
/// Data type for a properly aligned stack of N bytes
|
||||
#[repr(C, align(64))]
|
||||
pub struct Stack<const SIZE: usize> {
|
||||
/// Memory to be used for the stack
|
||||
pub mem: [u8; SIZE],
|
||||
}
|
||||
|
||||
impl<const SIZE: usize> Stack<SIZE> {
|
||||
/// Construct a stack of length SIZE, initialized to 0
|
||||
pub const fn new() -> Stack<SIZE> {
|
||||
Stack { mem: [0_u8; SIZE] }
|
||||
}
|
||||
}
|
||||
|
||||
static mut START_CORE1_FUNCTION: Option<&'static mut (dyn FnMut() + 'static)> = None;
|
||||
|
||||
static mut APP_CORE_STACK_TOP: Option<*mut u32> = None;
|
||||
|
||||
/// Will park the APP (second) core when dropped
|
||||
#[must_use]
|
||||
pub struct AppCoreGuard<'a> {
|
||||
@ -208,10 +228,6 @@ impl CpuControl {
|
||||
}
|
||||
|
||||
unsafe fn start_core1_init() -> ! {
|
||||
extern "C" {
|
||||
static mut _stack_end_cpu1: u32;
|
||||
}
|
||||
|
||||
// disables interrupts
|
||||
xtensa_lx::interrupt::set_mask(0);
|
||||
|
||||
@ -221,7 +237,7 @@ impl CpuControl {
|
||||
xtensa_lx::timer::set_ccompare2(0);
|
||||
|
||||
// set stack pointer to end of memory: no need to retain stack up to this point
|
||||
set_stack_pointer(&mut _stack_end_cpu1);
|
||||
set_stack_pointer(unsafe { APP_CORE_STACK_TOP.unwrap() });
|
||||
|
||||
extern "C" {
|
||||
static mut _init_start: u32;
|
||||
@ -246,8 +262,9 @@ impl CpuControl {
|
||||
/// The second core will start running the closure `entry`.
|
||||
///
|
||||
/// Dropping the returned guard will park the core.
|
||||
pub fn start_app_core<'a>(
|
||||
pub fn start_app_core<'a, const SIZE: usize>(
|
||||
&mut self,
|
||||
stack: &'static mut Stack<SIZE>,
|
||||
entry: &'a mut (dyn FnMut() + Send),
|
||||
) -> Result<AppCoreGuard<'a>, Error> {
|
||||
let dport_control = crate::peripherals::DPORT::PTR;
|
||||
@ -267,6 +284,9 @@ impl CpuControl {
|
||||
self.enable_cache(Cpu::AppCpu);
|
||||
|
||||
unsafe {
|
||||
let stack_size = (stack.mem.len() - 4) & !0xf;
|
||||
APP_CORE_STACK_TOP = Some((stack as *mut _ as usize + stack_size) as *mut u32);
|
||||
|
||||
let entry_fn: &'static mut (dyn FnMut() + 'static) = core::mem::transmute(entry);
|
||||
START_CORE1_FUNCTION = Some(entry_fn);
|
||||
}
|
||||
|
||||
@ -15,13 +15,17 @@
|
||||
//!
|
||||
//! ## Example
|
||||
//! ```no_run
|
||||
//! static mut APP_CORE_STACK: Stack<8192> = Stack::new();
|
||||
//!
|
||||
//! let counter = Mutex::new(RefCell::new(0));
|
||||
//!
|
||||
//! let mut cpu_control = CpuControl::new(system.cpu_control);
|
||||
//! let mut cpu1_fnctn = || {
|
||||
//! cpu1_task(&mut timer1, &counter);
|
||||
//! };
|
||||
//! let _guard = cpu_control.start_app_core(&mut cpu1_fnctn).unwrap();
|
||||
//! let _guard = cpu_control
|
||||
//! .start_app_core(unsafe { &mut APP_CORE_STACK }, &mut cpu1_fnctn)
|
||||
//! .unwrap();
|
||||
//!
|
||||
//! loop {
|
||||
//! block!(timer0.wait()).unwrap();
|
||||
@ -55,8 +59,24 @@ use xtensa_lx::set_stack_pointer;
|
||||
|
||||
use crate::Cpu;
|
||||
|
||||
/// Data type for a properly aligned stack of N bytes
|
||||
#[repr(C, align(64))]
|
||||
pub struct Stack<const SIZE: usize> {
|
||||
/// Memory to be used for the stack
|
||||
pub mem: [u8; SIZE],
|
||||
}
|
||||
|
||||
impl<const SIZE: usize> Stack<SIZE> {
|
||||
/// Construct a stack of length SIZE, initialized to 0
|
||||
pub const fn new() -> Stack<SIZE> {
|
||||
Stack { mem: [0_u8; SIZE] }
|
||||
}
|
||||
}
|
||||
|
||||
static mut START_CORE1_FUNCTION: Option<&'static mut (dyn FnMut() + 'static)> = None;
|
||||
|
||||
static mut APP_CORE_STACK_TOP: Option<*mut u32> = None;
|
||||
|
||||
/// Will park the APP (second) core when dropped
|
||||
#[must_use]
|
||||
pub struct AppCoreGuard<'a> {
|
||||
@ -143,10 +163,6 @@ impl CpuControl {
|
||||
}
|
||||
|
||||
unsafe fn start_core1_init() -> ! {
|
||||
extern "C" {
|
||||
static mut _stack_end_cpu1: u32;
|
||||
}
|
||||
|
||||
// disables interrupts
|
||||
xtensa_lx::interrupt::set_mask(0);
|
||||
|
||||
@ -156,7 +172,7 @@ impl CpuControl {
|
||||
xtensa_lx::timer::set_ccompare2(0);
|
||||
|
||||
// set stack pointer to end of memory: no need to retain stack up to this point
|
||||
set_stack_pointer(&mut _stack_end_cpu1);
|
||||
set_stack_pointer(unsafe { APP_CORE_STACK_TOP.unwrap() });
|
||||
|
||||
extern "C" {
|
||||
static mut _init_start: u32;
|
||||
@ -181,8 +197,9 @@ impl CpuControl {
|
||||
/// The second core will start running the closure `entry`.
|
||||
///
|
||||
/// Dropping the returned guard will park the core.
|
||||
pub fn start_app_core<'a>(
|
||||
pub fn start_app_core<'a, const SIZE: usize>(
|
||||
&mut self,
|
||||
stack: &'static mut Stack<SIZE>,
|
||||
entry: &'a mut (dyn FnMut() + Send),
|
||||
) -> Result<AppCoreGuard<'a>, Error> {
|
||||
let system_control = crate::peripherals::SYSTEM::PTR;
|
||||
@ -199,6 +216,9 @@ impl CpuControl {
|
||||
}
|
||||
|
||||
unsafe {
|
||||
let stack_size = (stack.mem.len() - 4) & !0xf;
|
||||
APP_CORE_STACK_TOP = Some((stack as *mut _ as usize + stack_size) as *mut u32);
|
||||
|
||||
let entry_fn: &'static mut (dyn FnMut() + 'static) = core::mem::transmute(entry);
|
||||
START_CORE1_FUNCTION = Some(entry_fn);
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "esp-riscv-rt"
|
||||
version = "0.4.0"
|
||||
version = "0.5.0"
|
||||
edition = "2021"
|
||||
rust-version = "1.65"
|
||||
description = "Minimal runtime / startup for RISC-V CPUs from Espressif"
|
||||
|
||||
@ -403,20 +403,8 @@ _abs_start:
|
||||
add t0, t0, %lo(_max_hart_id)
|
||||
bgtu t2, t0, abort
|
||||
|
||||
// Allocate stacks
|
||||
// Allocate stack
|
||||
la sp, _stack_start
|
||||
lui t0, %hi(_hart_stack_size)
|
||||
add t0, t0, %lo(_hart_stack_size)
|
||||
|
||||
beqz t2, 2f // Jump if single-hart
|
||||
mv t1, t2
|
||||
mv t3, t0
|
||||
1:
|
||||
add t0, t0, t3
|
||||
addi t1, t1, -1
|
||||
bnez t1, 1b
|
||||
2:
|
||||
sub sp, sp, t0
|
||||
|
||||
// Set frame pointer
|
||||
add s0, sp, zero
|
||||
|
||||
@ -52,9 +52,7 @@ fn generate_memory_extras() -> Vec<u8> {
|
||||
/* reserved at the start of the RTC memories for use by the ULP processor */
|
||||
RESERVE_RTC_FAST = 0;
|
||||
RESERVE_RTC_SLOW = 0;
|
||||
|
||||
/* define stack size for both cores */
|
||||
STACK_SIZE = 8k;"
|
||||
"
|
||||
)
|
||||
.as_bytes()
|
||||
.to_vec()
|
||||
|
||||
@ -10,7 +10,7 @@ use core::cell::RefCell;
|
||||
use critical_section::Mutex;
|
||||
use esp32_hal::{
|
||||
clock::ClockControl,
|
||||
cpu_control::CpuControl,
|
||||
cpu_control::{CpuControl, Stack},
|
||||
peripherals::{Peripherals, TIMG1},
|
||||
prelude::*,
|
||||
timer::{Timer, Timer0, TimerGroup},
|
||||
@ -20,6 +20,8 @@ use esp_backtrace as _;
|
||||
use esp_println::println;
|
||||
use nb::block;
|
||||
|
||||
static mut APP_CORE_STACK: Stack<8192> = Stack::new();
|
||||
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
let peripherals = Peripherals::take();
|
||||
@ -58,7 +60,9 @@ fn main() -> ! {
|
||||
let mut cpu1_fnctn = || {
|
||||
cpu1_task(&mut timer1, &counter);
|
||||
};
|
||||
let _guard = cpu_control.start_app_core(&mut cpu1_fnctn).unwrap();
|
||||
let _guard = cpu_control
|
||||
.start_app_core(unsafe { &mut APP_CORE_STACK }, &mut cpu1_fnctn)
|
||||
.unwrap();
|
||||
|
||||
loop {
|
||||
block!(timer0.wait()).unwrap();
|
||||
|
||||
@ -20,7 +20,6 @@ INCLUDE "rwtext.x"
|
||||
INCLUDE "rwdata.x"
|
||||
INCLUDE "rtc_fast.x"
|
||||
INCLUDE "rtc_slow.x"
|
||||
INCLUDE "external.x"
|
||||
/* End of Shared sections */
|
||||
|
||||
/* an uninitialized section for use as the wifi-heap in esp-wifi */
|
||||
@ -30,12 +29,14 @@ SECTIONS {
|
||||
} > dram2_seg
|
||||
}
|
||||
|
||||
_heap_end = ABSOLUTE(ORIGIN(dram_seg))+LENGTH(dram_seg) - 2*STACK_SIZE;
|
||||
_stack_region_top = ABSOLUTE(ORIGIN(dram_seg))+LENGTH(dram_seg);
|
||||
_stack_region_bottom = _stack_end;
|
||||
|
||||
_stack_start_cpu1 = _heap_end;
|
||||
_stack_end_cpu1 = _stack_start_cpu1 + STACK_SIZE;
|
||||
_stack_start_cpu0 = _stack_end_cpu1;
|
||||
_stack_end_cpu0 = _stack_start_cpu0 + STACK_SIZE;
|
||||
/*
|
||||
use the whole remaining memory as core-0's stack
|
||||
*/
|
||||
_stack_end_cpu0 = _stack_region_top;
|
||||
_stack_start_cpu0 = _stack_region_bottom;
|
||||
|
||||
EXTERN(DefaultHandler);
|
||||
|
||||
|
||||
@ -49,9 +49,5 @@ MEMORY
|
||||
|
||||
/* RTC slow memory (data accessible). Persists over deep sleep. */
|
||||
rtc_slow_seg(RW) : ORIGIN = 0x50000000 + RESERVE_RTC_SLOW, len = 8k - RESERVE_RTC_SLOW
|
||||
|
||||
/* external memory, including data and text,
|
||||
4MB is the maximum, if external psram is bigger, paging is required */
|
||||
psram_seg(RWX) : ORIGIN = 0x3F800000, len = 4M
|
||||
}
|
||||
|
||||
|
||||
@ -3,8 +3,6 @@ ENTRY(_start)
|
||||
PROVIDE(_stext = ORIGIN(ROTEXT));
|
||||
PROVIDE(_stack_start = ORIGIN(RWDATA) + LENGTH(RWDATA));
|
||||
PROVIDE(_max_hart_id = 0);
|
||||
PROVIDE(_hart_stack_size = 2K);
|
||||
PROVIDE(_heap_size = 0);
|
||||
|
||||
PROVIDE(UserSoft = DefaultHandler);
|
||||
PROVIDE(SupervisorSoft = DefaultHandler);
|
||||
|
||||
@ -31,7 +31,6 @@ REGION_ALIAS("REGION_RODATA", DROM);
|
||||
|
||||
REGION_ALIAS("REGION_DATA", DRAM);
|
||||
REGION_ALIAS("REGION_BSS", DRAM);
|
||||
REGION_ALIAS("REGION_HEAP", DRAM);
|
||||
REGION_ALIAS("REGION_STACK", DRAM);
|
||||
|
||||
REGION_ALIAS("REGION_RWTEXT", IRAM);
|
||||
|
||||
@ -3,8 +3,6 @@ ENTRY(_start)
|
||||
PROVIDE(_stext = ORIGIN(REGION_TEXT));
|
||||
PROVIDE(_stack_start = ORIGIN(REGION_STACK) + LENGTH(REGION_STACK));
|
||||
PROVIDE(_max_hart_id = 0);
|
||||
PROVIDE(_hart_stack_size = 2K);
|
||||
PROVIDE(_heap_size = 0);
|
||||
|
||||
PROVIDE(UserSoft = DefaultHandler);
|
||||
PROVIDE(SupervisorSoft = DefaultHandler);
|
||||
@ -113,15 +111,6 @@ SECTIONS
|
||||
_bss_end = .;
|
||||
} > REGION_BSS
|
||||
|
||||
/* fictitious region that represents the memory available for the heap */
|
||||
.heap (NOLOAD) :
|
||||
{
|
||||
_sheap = .;
|
||||
. += _heap_size;
|
||||
. = ALIGN(4);
|
||||
_eheap = .;
|
||||
} > REGION_HEAP
|
||||
|
||||
/* fictitious region that represents the memory available for the stack */
|
||||
.stack (NOLOAD) :
|
||||
{
|
||||
@ -156,9 +145,6 @@ ERROR(riscv-rt): the start of the REGION_RODATA must be 4-byte aligned");
|
||||
ASSERT(ORIGIN(REGION_DATA) % 4 == 0, "
|
||||
ERROR(riscv-rt): the start of the REGION_DATA must be 4-byte aligned");
|
||||
|
||||
ASSERT(ORIGIN(REGION_HEAP) % 4 == 0, "
|
||||
ERROR(riscv-rt): the start of the REGION_HEAP must be 4-byte aligned");
|
||||
|
||||
ASSERT(ORIGIN(REGION_TEXT) % 4 == 0, "
|
||||
ERROR(riscv-rt): the start of the REGION_TEXT must be 4-byte aligned");
|
||||
|
||||
@ -177,17 +163,10 @@ BUG(riscv-rt): the LMA of .data is not 4-byte aligned");
|
||||
ASSERT(_bss_start % 4 == 0 && _bss_end % 4 == 0, "
|
||||
BUG(riscv-rt): .bss is not 4-byte aligned");
|
||||
|
||||
ASSERT(_sheap % 4 == 0, "
|
||||
BUG(riscv-rt): start of .heap is not 4-byte aligned");
|
||||
|
||||
ASSERT(_stext + SIZEOF(.text) < ORIGIN(REGION_TEXT) + LENGTH(REGION_TEXT), "
|
||||
ERROR(riscv-rt): The .text section must be placed inside the REGION_TEXT region.
|
||||
Set _stext to an address smaller than 'ORIGIN(REGION_TEXT) + LENGTH(REGION_TEXT)'");
|
||||
|
||||
ASSERT(SIZEOF(.stack) > (_max_hart_id + 1) * _hart_stack_size, "
|
||||
ERROR(riscv-rt): .stack section is too small for allocating stacks for all the harts.
|
||||
Consider changing `_max_hart_id` or `_hart_stack_size`.");
|
||||
|
||||
ASSERT(SIZEOF(.got) == 0, "
|
||||
.got section detected in the input files. Dynamic relocations are not
|
||||
supported. If you are linking to C code compiled using the `gcc` crate
|
||||
|
||||
@ -3,8 +3,6 @@ ENTRY(_start)
|
||||
PROVIDE(_stext = ORIGIN(ROTEXT));
|
||||
PROVIDE(_stack_start = ORIGIN(RWDATA) + LENGTH(RWDATA));
|
||||
PROVIDE(_max_hart_id = 0);
|
||||
PROVIDE(_hart_stack_size = 2K);
|
||||
PROVIDE(_heap_size = 0);
|
||||
|
||||
PROVIDE(UserSoft = DefaultHandler);
|
||||
PROVIDE(SupervisorSoft = DefaultHandler);
|
||||
|
||||
@ -37,7 +37,6 @@ REGION_ALIAS("REGION_RODATA", DROM);
|
||||
|
||||
REGION_ALIAS("REGION_DATA", DRAM);
|
||||
REGION_ALIAS("REGION_BSS", DRAM);
|
||||
REGION_ALIAS("REGION_HEAP", DRAM);
|
||||
REGION_ALIAS("REGION_STACK", DRAM);
|
||||
|
||||
REGION_ALIAS("REGION_RWTEXT", IRAM);
|
||||
|
||||
@ -3,8 +3,6 @@ ENTRY(_start)
|
||||
PROVIDE(_stext = ORIGIN(REGION_TEXT));
|
||||
PROVIDE(_stack_start = ORIGIN(REGION_STACK) + LENGTH(REGION_STACK));
|
||||
PROVIDE(_max_hart_id = 0);
|
||||
PROVIDE(_hart_stack_size = 2K);
|
||||
PROVIDE(_heap_size = 0);
|
||||
|
||||
PROVIDE(UserSoft = DefaultHandler);
|
||||
PROVIDE(SupervisorSoft = DefaultHandler);
|
||||
@ -123,15 +121,6 @@ SECTIONS
|
||||
__euninit = .;
|
||||
} > REGION_BSS
|
||||
|
||||
/* fictitious region that represents the memory available for the heap */
|
||||
.heap (NOLOAD) :
|
||||
{
|
||||
_sheap = .;
|
||||
. += _heap_size;
|
||||
. = ALIGN(4);
|
||||
_eheap = .;
|
||||
} > REGION_HEAP
|
||||
|
||||
/* fictitious region that represents the memory available for the stack */
|
||||
.stack (NOLOAD) :
|
||||
{
|
||||
@ -198,9 +187,6 @@ ERROR(riscv-rt): the start of the REGION_RODATA must be 4-byte aligned");
|
||||
ASSERT(ORIGIN(REGION_DATA) % 4 == 0, "
|
||||
ERROR(riscv-rt): the start of the REGION_DATA must be 4-byte aligned");
|
||||
|
||||
ASSERT(ORIGIN(REGION_HEAP) % 4 == 0, "
|
||||
ERROR(riscv-rt): the start of the REGION_HEAP must be 4-byte aligned");
|
||||
|
||||
ASSERT(ORIGIN(REGION_TEXT) % 4 == 0, "
|
||||
ERROR(riscv-rt): the start of the REGION_TEXT must be 4-byte aligned");
|
||||
|
||||
@ -219,17 +205,10 @@ BUG(riscv-rt): the LMA of .data is not 4-byte aligned");
|
||||
ASSERT(_bss_start % 4 == 0 && _bss_end % 4 == 0, "
|
||||
BUG(riscv-rt): .bss is not 4-byte aligned");
|
||||
|
||||
ASSERT(_sheap % 4 == 0, "
|
||||
BUG(riscv-rt): start of .heap is not 4-byte aligned");
|
||||
|
||||
ASSERT(_stext + SIZEOF(.text) < ORIGIN(REGION_TEXT) + LENGTH(REGION_TEXT), "
|
||||
ERROR(riscv-rt): The .text section must be placed inside the REGION_TEXT region.
|
||||
Set _stext to an address smaller than 'ORIGIN(REGION_TEXT) + LENGTH(REGION_TEXT)'");
|
||||
|
||||
ASSERT(SIZEOF(.stack) > (_max_hart_id + 1) * _hart_stack_size, "
|
||||
ERROR(riscv-rt): .stack section is too small for allocating stacks for all the harts.
|
||||
Consider changing `_max_hart_id` or `_hart_stack_size`.");
|
||||
|
||||
ASSERT(SIZEOF(.got) == 0, "
|
||||
.got section detected in the input files. Dynamic relocations are not
|
||||
supported. If you are linking to C code compiled using the `gcc` crate
|
||||
|
||||
@ -59,7 +59,6 @@ REGION_ALIAS("REGION_RODATA", DROM);
|
||||
|
||||
REGION_ALIAS("REGION_DATA", DRAM);
|
||||
REGION_ALIAS("REGION_BSS", DRAM);
|
||||
REGION_ALIAS("REGION_HEAP", DRAM);
|
||||
REGION_ALIAS("REGION_STACK", DRAM);
|
||||
|
||||
REGION_ALIAS("REGION_RWTEXT", IRAM);
|
||||
|
||||
@ -2,8 +2,6 @@ ENTRY(_start)
|
||||
|
||||
PROVIDE(_stack_start = ORIGIN(REGION_STACK) + LENGTH(REGION_STACK));
|
||||
PROVIDE(_max_hart_id = 0);
|
||||
PROVIDE(_hart_stack_size = 2K);
|
||||
PROVIDE(_heap_size = 0);
|
||||
|
||||
PROVIDE(UserSoft = DefaultHandler);
|
||||
PROVIDE(SupervisorSoft = DefaultHandler);
|
||||
@ -114,15 +112,6 @@ SECTIONS
|
||||
_data_end = .;
|
||||
} > REGION_DATA AT>ROM
|
||||
|
||||
/* fictitious region that represents the memory available for the heap */
|
||||
.heap (NOLOAD) :
|
||||
{
|
||||
_sheap = .;
|
||||
. += _heap_size;
|
||||
. = ALIGN(4);
|
||||
_eheap = .;
|
||||
} > REGION_HEAP
|
||||
|
||||
/* fictitious region that represents the memory available for the stack */
|
||||
.stack (NOLOAD) :
|
||||
{
|
||||
@ -218,9 +207,6 @@ ERROR(riscv-rt): the start of the REGION_RODATA must be 4-byte aligned");
|
||||
ASSERT(ORIGIN(REGION_DATA) % 4 == 0, "
|
||||
ERROR(riscv-rt): the start of the REGION_DATA must be 4-byte aligned");
|
||||
|
||||
ASSERT(ORIGIN(REGION_HEAP) % 4 == 0, "
|
||||
ERROR(riscv-rt): the start of the REGION_HEAP must be 4-byte aligned");
|
||||
|
||||
ASSERT(ORIGIN(REGION_TEXT) % 4 == 0, "
|
||||
ERROR(riscv-rt): the start of the REGION_TEXT must be 4-byte aligned");
|
||||
|
||||
@ -239,17 +225,10 @@ BUG(riscv-rt): the LMA of .data is not 4-byte aligned");
|
||||
ASSERT(_bss_start % 4 == 0 && _bss_end % 4 == 0, "
|
||||
BUG(riscv-rt): .bss is not 4-byte aligned");
|
||||
|
||||
ASSERT(_sheap % 4 == 0, "
|
||||
BUG(riscv-rt): start of .heap is not 4-byte aligned");
|
||||
|
||||
ASSERT(_stext + SIZEOF(.text) < ORIGIN(REGION_TEXT) + LENGTH(REGION_TEXT), "
|
||||
ERROR(riscv-rt): The .text section must be placed inside the REGION_TEXT region.
|
||||
Set _stext to an address smaller than 'ORIGIN(REGION_TEXT) + LENGTH(REGION_TEXT)'");
|
||||
|
||||
ASSERT(SIZEOF(.stack) > (_max_hart_id + 1) * _hart_stack_size, "
|
||||
ERROR(riscv-rt): .stack section is too small for allocating stacks for all the harts.
|
||||
Consider changing `_max_hart_id` or `_hart_stack_size`.");
|
||||
|
||||
ASSERT(SIZEOF(.got) == 0, "
|
||||
.got section detected in the input files. Dynamic relocations are not
|
||||
supported. If you are linking to C code compiled using the `gcc` crate
|
||||
|
||||
@ -3,8 +3,6 @@ ENTRY(_start)
|
||||
PROVIDE(_stext = ORIGIN(ROTEXT));
|
||||
PROVIDE(_stack_start = ORIGIN(RWDATA) + LENGTH(RWDATA));
|
||||
PROVIDE(_max_hart_id = 0);
|
||||
PROVIDE(_hart_stack_size = 2K);
|
||||
PROVIDE(_heap_size = 0);
|
||||
|
||||
PROVIDE(UserSoft = DefaultHandler);
|
||||
PROVIDE(SupervisorSoft = DefaultHandler);
|
||||
|
||||
@ -31,7 +31,6 @@ REGION_ALIAS("REGION_RODATA", ROM);
|
||||
|
||||
REGION_ALIAS("REGION_DATA", RAM);
|
||||
REGION_ALIAS("REGION_BSS", RAM);
|
||||
REGION_ALIAS("REGION_HEAP", RAM);
|
||||
REGION_ALIAS("REGION_STACK", RAM);
|
||||
|
||||
REGION_ALIAS("REGION_RWTEXT", RAM);
|
||||
|
||||
@ -3,8 +3,6 @@ ENTRY(_start)
|
||||
PROVIDE(_stext = ORIGIN(REGION_TEXT));
|
||||
PROVIDE(_stack_start = ORIGIN(REGION_STACK) + LENGTH(REGION_STACK));
|
||||
PROVIDE(_max_hart_id = 0);
|
||||
PROVIDE(_hart_stack_size = 2K);
|
||||
PROVIDE(_heap_size = 0);
|
||||
|
||||
PROVIDE(UserSoft = DefaultHandler);
|
||||
PROVIDE(SupervisorSoft = DefaultHandler);
|
||||
@ -150,15 +148,6 @@ SECTIONS
|
||||
__euninit = .;
|
||||
} > REGION_BSS
|
||||
|
||||
/* fictitious region that represents the memory available for the heap */
|
||||
.heap (NOLOAD) :
|
||||
{
|
||||
_sheap = .;
|
||||
. += _heap_size;
|
||||
. = ALIGN(4);
|
||||
_eheap = .;
|
||||
} > REGION_HEAP
|
||||
|
||||
/* fictitious region that represents the memory available for the stack */
|
||||
.stack (NOLOAD) :
|
||||
{
|
||||
@ -195,9 +184,6 @@ ERROR(riscv-rt): the start of the REGION_RODATA must be 4-byte aligned");
|
||||
ASSERT(ORIGIN(REGION_DATA) % 4 == 0, "
|
||||
ERROR(riscv-rt): the start of the REGION_DATA must be 4-byte aligned");
|
||||
|
||||
ASSERT(ORIGIN(REGION_HEAP) % 4 == 0, "
|
||||
ERROR(riscv-rt): the start of the REGION_HEAP must be 4-byte aligned");
|
||||
|
||||
ASSERT(ORIGIN(REGION_TEXT) % 4 == 0, "
|
||||
ERROR(riscv-rt): the start of the REGION_TEXT must be 4-byte aligned");
|
||||
|
||||
@ -216,17 +202,10 @@ BUG(riscv-rt): the LMA of .data is not 4-byte aligned");
|
||||
ASSERT(_bss_start % 4 == 0 && _bss_end % 4 == 0, "
|
||||
BUG(riscv-rt): .bss is not 4-byte aligned");
|
||||
|
||||
ASSERT(_sheap % 4 == 0, "
|
||||
BUG(riscv-rt): start of .heap is not 4-byte aligned");
|
||||
|
||||
ASSERT(_stext + SIZEOF(.text) < ORIGIN(REGION_TEXT) + LENGTH(REGION_TEXT), "
|
||||
ERROR(riscv-rt): The .text section must be placed inside the REGION_TEXT region.
|
||||
Set _stext to an address smaller than 'ORIGIN(REGION_TEXT) + LENGTH(REGION_TEXT)'");
|
||||
|
||||
ASSERT(SIZEOF(.stack) > (_max_hart_id + 1) * _hart_stack_size, "
|
||||
ERROR(riscv-rt): .stack section is too small for allocating stacks for all the harts.
|
||||
Consider changing `_max_hart_id` or `_hart_stack_size`.");
|
||||
|
||||
ASSERT(SIZEOF(.got) == 0, "
|
||||
.got section detected in the input files. Dynamic relocations are not
|
||||
supported. If you are linking to C code compiled using the `gcc` crate
|
||||
|
||||
@ -3,8 +3,6 @@ ENTRY(_start)
|
||||
PROVIDE(_stext = ORIGIN(ROTEXT));
|
||||
PROVIDE(_stack_start = ORIGIN(RWDATA) + LENGTH(RWDATA));
|
||||
PROVIDE(_max_hart_id = 0);
|
||||
PROVIDE(_hart_stack_size = 2K);
|
||||
PROVIDE(_heap_size = 0);
|
||||
|
||||
PROVIDE(UserSoft = DefaultHandler);
|
||||
PROVIDE(SupervisorSoft = DefaultHandler);
|
||||
|
||||
@ -32,7 +32,6 @@ REGION_ALIAS("REGION_RODATA", ROM);
|
||||
|
||||
REGION_ALIAS("REGION_DATA", RAM);
|
||||
REGION_ALIAS("REGION_BSS", RAM);
|
||||
REGION_ALIAS("REGION_HEAP", RAM);
|
||||
REGION_ALIAS("REGION_STACK", RAM);
|
||||
|
||||
REGION_ALIAS("REGION_RWTEXT", RAM);
|
||||
|
||||
@ -3,8 +3,6 @@ ENTRY(_start)
|
||||
PROVIDE(_stext = ORIGIN(REGION_TEXT));
|
||||
PROVIDE(_stack_start = ORIGIN(REGION_STACK) + LENGTH(REGION_STACK));
|
||||
PROVIDE(_max_hart_id = 0);
|
||||
PROVIDE(_hart_stack_size = 2K);
|
||||
PROVIDE(_heap_size = 0);
|
||||
|
||||
PROVIDE(UserSoft = DefaultHandler);
|
||||
PROVIDE(SupervisorSoft = DefaultHandler);
|
||||
@ -150,15 +148,6 @@ SECTIONS
|
||||
__euninit = .;
|
||||
} > REGION_BSS
|
||||
|
||||
/* fictitious region that represents the memory available for the heap */
|
||||
.heap (NOLOAD) :
|
||||
{
|
||||
_sheap = .;
|
||||
. += _heap_size;
|
||||
. = ALIGN(4);
|
||||
_eheap = .;
|
||||
} > REGION_HEAP
|
||||
|
||||
/* fictitious region that represents the memory available for the stack */
|
||||
.stack (NOLOAD) :
|
||||
{
|
||||
@ -195,9 +184,6 @@ ERROR(riscv-rt): the start of the REGION_RODATA must be 4-byte aligned");
|
||||
ASSERT(ORIGIN(REGION_DATA) % 4 == 0, "
|
||||
ERROR(riscv-rt): the start of the REGION_DATA must be 4-byte aligned");
|
||||
|
||||
ASSERT(ORIGIN(REGION_HEAP) % 4 == 0, "
|
||||
ERROR(riscv-rt): the start of the REGION_HEAP must be 4-byte aligned");
|
||||
|
||||
ASSERT(ORIGIN(REGION_TEXT) % 4 == 0, "
|
||||
ERROR(riscv-rt): the start of the REGION_TEXT must be 4-byte aligned");
|
||||
|
||||
@ -216,17 +202,10 @@ BUG(riscv-rt): the LMA of .data is not 4-byte aligned");
|
||||
ASSERT(_bss_start % 4 == 0 && _bss_end % 4 == 0, "
|
||||
BUG(riscv-rt): .bss is not 4-byte aligned");
|
||||
|
||||
ASSERT(_sheap % 4 == 0, "
|
||||
BUG(riscv-rt): start of .heap is not 4-byte aligned");
|
||||
|
||||
ASSERT(_stext + SIZEOF(.text) < ORIGIN(REGION_TEXT) + LENGTH(REGION_TEXT), "
|
||||
ERROR(riscv-rt): The .text section must be placed inside the REGION_TEXT region.
|
||||
Set _stext to an address smaller than 'ORIGIN(REGION_TEXT) + LENGTH(REGION_TEXT)'");
|
||||
|
||||
ASSERT(SIZEOF(.stack) > (_max_hart_id + 1) * _hart_stack_size, "
|
||||
ERROR(riscv-rt): .stack section is too small for allocating stacks for all the harts.
|
||||
Consider changing `_max_hart_id` or `_hart_stack_size`.");
|
||||
|
||||
ASSERT(SIZEOF(.got) == 0, "
|
||||
.got section detected in the input files. Dynamic relocations are not
|
||||
supported. If you are linking to C code compiled using the `gcc` crate
|
||||
|
||||
@ -28,13 +28,13 @@ INCLUDE "rwtext.x"
|
||||
INCLUDE "rwdata.x"
|
||||
INCLUDE "rtc_fast.x"
|
||||
INCLUDE "rtc_slow.x"
|
||||
INCLUDE "external.x"
|
||||
/* End of Shared sections */
|
||||
|
||||
_heap_end = ABSOLUTE(ORIGIN(dram_seg))+LENGTH(dram_seg) - STACK_SIZE;
|
||||
_stack_region_top = ABSOLUTE(ORIGIN(dram_seg))+LENGTH(dram_seg);
|
||||
_stack_region_bottom = _stack_end;
|
||||
|
||||
_stack_start_cpu0 = _heap_end;
|
||||
_stack_end_cpu0 = _stack_start_cpu0 + STACK_SIZE;
|
||||
_stack_end_cpu0 = _stack_region_top;
|
||||
_stack_start_cpu0 = _stack_region_bottom;
|
||||
|
||||
EXTERN(DefaultHandler);
|
||||
|
||||
|
||||
@ -16,9 +16,6 @@ VECTORS_SIZE = 0x400;
|
||||
RESERVE_RTC_FAST = 0;
|
||||
RESERVE_RTC_SLOW = 0;
|
||||
|
||||
/* define stack size for both cores */
|
||||
STACK_SIZE = 8k;
|
||||
|
||||
/* Specify main memory areas */
|
||||
MEMORY
|
||||
{
|
||||
@ -46,7 +43,4 @@ MEMORY
|
||||
|
||||
/* RTC slow memory (data accessible). Persists over deep sleep. */
|
||||
rtc_slow_seg(RW) : ORIGIN = 0x50000000 + RESERVE_RTC_SLOW, len = 8k - RESERVE_RTC_SLOW
|
||||
|
||||
/* external memory, including data and text */
|
||||
psram_seg(RWX) : ORIGIN = 0x3F500000, len = 0xA80000
|
||||
}
|
||||
|
||||
@ -10,7 +10,7 @@ use core::cell::RefCell;
|
||||
use critical_section::Mutex;
|
||||
use esp32s3_hal::{
|
||||
clock::ClockControl,
|
||||
cpu_control::CpuControl,
|
||||
cpu_control::{CpuControl, Stack},
|
||||
peripherals::{Peripherals, TIMG1},
|
||||
prelude::*,
|
||||
timer::{Timer, Timer0, TimerGroup},
|
||||
@ -20,6 +20,8 @@ use esp_backtrace as _;
|
||||
use esp_println::println;
|
||||
use nb::block;
|
||||
|
||||
static mut APP_CORE_STACK: Stack<8192> = Stack::new();
|
||||
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
let peripherals = Peripherals::take();
|
||||
@ -58,7 +60,9 @@ fn main() -> ! {
|
||||
let mut cpu1_fnctn = || {
|
||||
cpu1_task(&mut timer1, &counter);
|
||||
};
|
||||
let _guard = cpu_control.start_app_core(&mut cpu1_fnctn).unwrap();
|
||||
let _guard = cpu_control
|
||||
.start_app_core(unsafe { &mut APP_CORE_STACK }, &mut cpu1_fnctn)
|
||||
.unwrap();
|
||||
|
||||
loop {
|
||||
block!(timer0.wait()).unwrap();
|
||||
|
||||
@ -1,17 +1,14 @@
|
||||
/* before memory.x to allow override */
|
||||
ENTRY(Reset)
|
||||
|
||||
_external_ram_start = ABSOLUTE(ORIGIN(psram_seg));
|
||||
_external_ram_end = ABSOLUTE(ORIGIN(psram_seg)+LENGTH(psram_seg));
|
||||
_stack_region_top = ABSOLUTE(ORIGIN(dram_seg))+LENGTH(dram_seg);
|
||||
_stack_region_bottom = _stack_end;
|
||||
|
||||
_heap_end = ABSOLUTE(ORIGIN(dram_seg))+LENGTH(dram_seg)+LENGTH(reserved_for_boot_seg) - 2*STACK_SIZE;
|
||||
_text_heap_end = ABSOLUTE(ORIGIN(iram_seg)+LENGTH(iram_seg));
|
||||
_external_heap_end = ABSOLUTE(ORIGIN(psram_seg)+LENGTH(psram_seg));
|
||||
|
||||
_stack_start_cpu1 = _heap_end;
|
||||
_stack_end_cpu1 = _stack_start_cpu1 + STACK_SIZE;
|
||||
_stack_start_cpu0 = _stack_end_cpu1;
|
||||
_stack_end_cpu0 = _stack_start_cpu0 + STACK_SIZE;
|
||||
/*
|
||||
use the whole remaining memory as core-0's stack
|
||||
*/
|
||||
_stack_end_cpu0 = _stack_region_top;
|
||||
_stack_start_cpu0 = _stack_region_bottom;
|
||||
|
||||
EXTERN(DefaultHandler);
|
||||
|
||||
@ -187,6 +184,13 @@ SECTIONS {
|
||||
. = ALIGN (4);
|
||||
} > RWDATA
|
||||
|
||||
/* must be last segment using RWDATA */
|
||||
.stack_end (NOLOAD) : ALIGN(4)
|
||||
{
|
||||
. = ALIGN (4);
|
||||
_stack_end = ABSOLUTE(.);
|
||||
} > RWDATA
|
||||
|
||||
.rtc_fast.text ORIGIN(rtc_fast_iram_seg) :
|
||||
AT(_text_size + SIZEOF(.header) + SIZEOF(.pre_header) + SIZEOF(.rodata) + SIZEOF(.rwtext) )
|
||||
{
|
||||
@ -270,37 +274,4 @@ SECTIONS {
|
||||
*(.rtc_slow.noinit .rtc_slow.noinit.*)
|
||||
. = ALIGN (4);
|
||||
}
|
||||
|
||||
.external.data :
|
||||
{
|
||||
_external_data_start = ABSOLUTE(.);
|
||||
. = ALIGN(4);
|
||||
*(.external.data .external.data.*)
|
||||
. = ALIGN (4);
|
||||
_external_data_end = ABSOLUTE(.);
|
||||
} > psram_seg AT > RODATA
|
||||
|
||||
.external.bss (NOLOAD) :
|
||||
{
|
||||
_external_bss_start = ABSOLUTE(.);
|
||||
. = ALIGN(4);
|
||||
*(.external.bss .external.bss.*)
|
||||
. = ALIGN (4);
|
||||
_external_bss_end = ABSOLUTE(.);
|
||||
} > psram_seg
|
||||
|
||||
.external.noinit (NOLOAD) :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
*(.external.noinit .external.noinit.*)
|
||||
. = ALIGN (4);
|
||||
} > psram_seg
|
||||
|
||||
/* must be last segment using psram_seg */
|
||||
.external_heap_start (NOLOAD) :
|
||||
{
|
||||
. = ALIGN (4);
|
||||
_external_heap_start = ABSOLUTE(.);
|
||||
. = ALIGN (4);
|
||||
} > psram_seg
|
||||
}
|
||||
|
||||
@ -8,9 +8,6 @@ RESERVE_DRAM = 0x8000;
|
||||
RESERVE_RTC_FAST = 0;
|
||||
RESERVE_RTC_SLOW = 0;
|
||||
|
||||
/* define stack size for both cores */
|
||||
STACK_SIZE = 8k;
|
||||
|
||||
/* Specify main memory areas */
|
||||
MEMORY
|
||||
{
|
||||
@ -38,7 +35,4 @@ MEMORY
|
||||
|
||||
/* RTC slow memory (data accessible). Persists over deep sleep. */
|
||||
rtc_slow_seg(RW) : ORIGIN = 0x50000000 + RESERVE_RTC_SLOW, len = 8k - RESERVE_RTC_SLOW
|
||||
|
||||
/* external memory, including data and text */
|
||||
psram_seg(RWX) : ORIGIN = 0x3F500000, len = 0xA80000 /* ??? */
|
||||
}
|
||||
|
||||
@ -43,15 +43,16 @@ INCLUDE "rwtext.x"
|
||||
INCLUDE "rwdata.x"
|
||||
INCLUDE "rtc_fast.x"
|
||||
INCLUDE "rtc_slow.x"
|
||||
INCLUDE "external.x"
|
||||
/* End of Shared sections */
|
||||
|
||||
_heap_end = ABSOLUTE(ORIGIN(dram_seg))+LENGTH(dram_seg) - 2*STACK_SIZE;
|
||||
_stack_region_top = ABSOLUTE(ORIGIN(dram_seg))+LENGTH(dram_seg);
|
||||
_stack_region_bottom = _stack_end;
|
||||
|
||||
_stack_start_cpu1 = _heap_end;
|
||||
_stack_end_cpu1 = _stack_start_cpu1 + STACK_SIZE;
|
||||
_stack_start_cpu0 = _stack_end_cpu1;
|
||||
_stack_end_cpu0 = _stack_start_cpu0 + STACK_SIZE;
|
||||
/*
|
||||
use the whole remaining memory as core-0's stack
|
||||
*/
|
||||
_stack_end_cpu0 = _stack_region_top;
|
||||
_stack_start_cpu0 = _stack_region_bottom;
|
||||
|
||||
EXTERN(DefaultHandler);
|
||||
|
||||
|
||||
@ -8,9 +8,6 @@ RESERVE_ICACHE = 0x8000;
|
||||
RESERVE_RTC_FAST = 0;
|
||||
RESERVE_RTC_SLOW = 0;
|
||||
|
||||
/* define stack size for both cores */
|
||||
STACK_SIZE = 8k;
|
||||
|
||||
VECTORS_SIZE = 0x400;
|
||||
|
||||
/* Specify main memory areas
|
||||
@ -50,7 +47,4 @@ MEMORY
|
||||
|
||||
/* RTC slow memory (data accessible). Persists over deep sleep. */
|
||||
rtc_slow_seg(RW) : ORIGIN = 0x50000000 + RESERVE_RTC_SLOW, len = 8k - RESERVE_RTC_SLOW
|
||||
|
||||
/* external memory, including data and text */
|
||||
psram_seg(RWX) : ORIGIN = 0x3F500000, len = 0xA80000 /* ??? */
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user