Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add linker script for external ram #1090

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions esp-hal-common/ld/esp32s3/esp32s3.x
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ SECTIONS {
INSERT BEFORE .data;

INCLUDE "fixups/rodata_dummy.x"
INCLUDE "fixups/external_ram_dummy.x"
/* End of ESP32S3 fixups */

/* Shared sections - ordering matters */
Expand All @@ -44,6 +45,7 @@ INCLUDE "rwdata.x"
INCLUDE "rtc_fast.x"
INCLUDE "rtc_slow.x"
INCLUDE "stack.x"
INCLUDE "external.x"
/* End of Shared sections */

EXTERN(DefaultHandler);
Expand Down
5 changes: 4 additions & 1 deletion esp-hal-common/ld/esp32s3/memory.x
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,11 @@ MEMORY


/* RTC fast memory (executable). Persists over deep sleep. Only for core 0 (PRO_CPU) */
rtc_fast_seg(RWX) : ORIGIN = 0x600fe000, len = 8k
rtc_fast_seg(RWX) : ORIGIN = 0x600fe000, len = 8k

/* RTC slow memory (data accessible). Persists over deep sleep. */
rtc_slow_seg(RW) : ORIGIN = 0x50000000, len = 8k

/* external memory, including data and text */
psram_seg(RWX) : ORIGIN = 0x3C000020, len = 32M - 0x20
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we should have that +0x20 here - it's used for mapped flash

  /**
   * (0x20 offset above is a convenience for the app binary image generation.
   * Flash cache has 64KB pages. The .bin file which is flashed to the chip
   * has a 0x18 byte file header, and each segment has a 0x08 byte segment
   * header. Setting this offset makes it simple to meet the flash cache MMU's
   * constraint that (paddr % 64KB == vaddr % 64KB).)
   */

}
36 changes: 36 additions & 0 deletions esp-hal-common/ld/sections/external.x
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@


SECTIONS {
.external.data :
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To support .data in ext-ram we would need a way to copy the initial data here

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I know. I just want to first understand if I took everything into account for bss, at least 😅

{
_external_data_start = ABSOLUTE(.);
_external_no_heap_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));
17 changes: 17 additions & 0 deletions esp-hal-common/ld/sections/fixups/external_ram_dummy.x
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/*
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we need this dummy section

* This section is required to skip flash rodata sections, because `psram_seg`
* and `drom_seg` are on the same bus
*/

SECTIONS {
.ext_ram_dummy (NOLOAD) :
{
. = ORIGIN(psram_seg) + (_rodata_reserved_end - _rodata_dummy_start);

/* Prepare the alignment of the section above
*/

. = ALIGN(0x10000);
} > psram_seg
}
INSERT BEFORE .external.data;
1 change: 1 addition & 0 deletions esp-hal-common/ld/sections/fixups/rodata_dummy.x
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ SECTIONS {
* Thus, it must have its alignment and (at least) its size.
*/

_rodata_dummy_start = ABSOLUTE(.);
/* Start at the same alignment constraint than .flash.text */

. = ALIGN(ALIGNOF(.text));
Expand Down
1 change: 1 addition & 0 deletions esp-hal-common/ld/sections/rodata.x
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ SECTIONS {
{
. = ALIGN(4);
*( .rodata_wlog_*.* )
_rodata_reserved_end = ABSOLUTE(.);
. = ALIGN(4);
} > RODATA
}
50 changes: 33 additions & 17 deletions esp-hal-common/src/soc/esp32s3/psram.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,17 @@ pub fn psram_vaddr_start() -> usize {
unsafe { PSRAM_VADDR as usize }
}

pub fn psram_vaddr_heap_start() -> usize {
extern "C" {
static mut _external_heap_start: u32;
}
unsafe { (&_external_heap_start as *const u32) as usize }
}

pub fn psram_heap_size() -> usize {
PSRAM_BYTES - (psram_vaddr_heap_start() - psram_vaddr_start())
}

cfg_if::cfg_if! {
if #[cfg(feature = "psram-2m")] {
const PSRAM_SIZE: u32 = 2;
Expand Down Expand Up @@ -57,6 +68,8 @@ pub const PSRAM_BYTES: usize = PSRAM_SIZE as usize * 1024 * 1024;
feature = "opsram-16m"
))]
pub fn init_psram(_peripheral: impl crate::peripheral::Peripheral<P = crate::peripherals::PSRAM>) {
use procmacros::ram;

const CONFIG_ESP32S3_INSTRUCTION_CACHE_SIZE: u32 = 0x4000;
const CONFIG_ESP32S3_ICACHE_ASSOCIATED_WAYS: u8 = 8;
const CONFIG_ESP32S3_INSTRUCTION_CACHE_LINE_SIZE: u8 = 32;
Expand All @@ -67,6 +80,11 @@ pub fn init_psram(_peripheral: impl crate::peripheral::Peripheral<P = crate::per
const START_PAGE: u32 = 0;

extern "C" {
static mut _external_no_heap_start: u32;

static mut _external_bss_start: u32;
static mut _external_bss_end: u32;

fn rom_config_instruction_cache_mode(
cfg_cache_size: u32,
cfg_cache_ways: u8,
Expand Down Expand Up @@ -101,24 +119,9 @@ pub fn init_psram(_peripheral: impl crate::peripheral::Peripheral<P = crate::per
) -> i32;
}
unsafe {
const MMU_PAGE_SIZE: u32 = 0x10000;
const ICACHE_MMU_SIZE: usize = 0x800;
const FLASH_MMU_TABLE_SIZE: usize = ICACHE_MMU_SIZE / core::mem::size_of::<u32>();
const MMU_INVALID: u32 = 1 << 14;
const DR_REG_MMU_TABLE: u32 = 0x600C5000;

// calculate the PSRAM start address to map
let mut start = PSRAM_VADDR;
let mmu_table_ptr = DR_REG_MMU_TABLE as *const u32;
for i in 0..FLASH_MMU_TABLE_SIZE {
if mmu_table_ptr.add(i).read_volatile() != MMU_INVALID {
start += MMU_PAGE_SIZE;
} else {
break;
}
}
debug!("PSRAM start address = {:x}", start);
PSRAM_VADDR = start;
PSRAM_VADDR = (&_external_no_heap_start as *const u32) as u32;
debug!("PSRAM start address = {:x}", PSRAM_VADDR);

// Configure the mode of instruction cache : cache size, cache line size.
rom_config_instruction_cache_mode(
Expand Down Expand Up @@ -161,6 +164,19 @@ pub fn init_psram(_peripheral: impl crate::peripheral::Peripheral<P = crate::per
}

utils::psram_init();
zero_bss();

#[ram]
fn zero_bss() {
extern "Rust" {
fn __zero_bss() -> bool;
}
unsafe {
if __zero_bss() {
crate::xtensa_lx_rt::zero_bss(&mut _external_bss_start, &mut _external_bss_end);
}
}
}
}

#[cfg(any(feature = "psram-2m", feature = "psram-4m", feature = "psram-8m"))]
Expand Down
Loading