user app can invoke kernel syscall!!!!
This commit is contained in:
79
Cargo.lock
generated
79
Cargo.lock
generated
@@ -1158,6 +1158,45 @@ dependencies = [
|
|||||||
"cpufeatures",
|
"cpufeatures",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "kernel"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"abi",
|
||||||
|
"bitflags 2.9.1",
|
||||||
|
"bt-hci",
|
||||||
|
"cortex-m",
|
||||||
|
"cortex-m-rt",
|
||||||
|
"cyw43",
|
||||||
|
"cyw43-pio",
|
||||||
|
"defmt 0.3.100",
|
||||||
|
"defmt-rtt",
|
||||||
|
"embassy-embedded-hal",
|
||||||
|
"embassy-executor",
|
||||||
|
"embassy-futures",
|
||||||
|
"embassy-rp 0.4.0",
|
||||||
|
"embassy-sync 0.7.0",
|
||||||
|
"embassy-time",
|
||||||
|
"embassy-usb",
|
||||||
|
"embedded-graphics",
|
||||||
|
"embedded-hal 0.2.7",
|
||||||
|
"embedded-hal-async",
|
||||||
|
"embedded-hal-bus",
|
||||||
|
"embedded-layout",
|
||||||
|
"embedded-sdmmc",
|
||||||
|
"goblin",
|
||||||
|
"heapless",
|
||||||
|
"num_enum 0.7.4",
|
||||||
|
"panic-probe",
|
||||||
|
"portable-atomic",
|
||||||
|
"shared",
|
||||||
|
"spin",
|
||||||
|
"st7365p-lcd",
|
||||||
|
"static_cell",
|
||||||
|
"talc",
|
||||||
|
"trouble-host",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lalrpop"
|
name = "lalrpop"
|
||||||
version = "0.19.12"
|
version = "0.19.12"
|
||||||
@@ -1428,46 +1467,6 @@ version = "0.5.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5be167a7af36ee22fe3115051bc51f6e6c7054c9348e28deb4f49bd6f705a315"
|
checksum = "5be167a7af36ee22fe3115051bc51f6e6c7054c9348e28deb4f49bd6f705a315"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "picocalc-os-rs"
|
|
||||||
version = "0.1.0"
|
|
||||||
dependencies = [
|
|
||||||
"abi",
|
|
||||||
"bitflags 2.9.1",
|
|
||||||
"bt-hci",
|
|
||||||
"bumpalo",
|
|
||||||
"cortex-m",
|
|
||||||
"cortex-m-rt",
|
|
||||||
"cyw43",
|
|
||||||
"cyw43-pio",
|
|
||||||
"defmt 0.3.100",
|
|
||||||
"defmt-rtt",
|
|
||||||
"embassy-embedded-hal",
|
|
||||||
"embassy-executor",
|
|
||||||
"embassy-futures",
|
|
||||||
"embassy-rp 0.4.0",
|
|
||||||
"embassy-sync 0.7.0",
|
|
||||||
"embassy-time",
|
|
||||||
"embassy-usb",
|
|
||||||
"embedded-graphics",
|
|
||||||
"embedded-hal 0.2.7",
|
|
||||||
"embedded-hal-async",
|
|
||||||
"embedded-hal-bus",
|
|
||||||
"embedded-layout",
|
|
||||||
"embedded-sdmmc",
|
|
||||||
"goblin",
|
|
||||||
"heapless",
|
|
||||||
"num_enum 0.7.4",
|
|
||||||
"panic-probe",
|
|
||||||
"portable-atomic",
|
|
||||||
"shared",
|
|
||||||
"spin",
|
|
||||||
"st7365p-lcd",
|
|
||||||
"static_cell",
|
|
||||||
"talc",
|
|
||||||
"trouble-host",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pin-project-lite"
|
name = "pin-project-lite"
|
||||||
version = "0.2.16"
|
version = "0.2.16"
|
||||||
|
|||||||
@@ -3,8 +3,16 @@
|
|||||||
use core::ffi::c_void;
|
use core::ffi::c_void;
|
||||||
use shared::keyboard::{KeyCode, KeyEvent, KeyState, Modifiers};
|
use shared::keyboard::{KeyCode, KeyEvent, KeyState, Modifiers};
|
||||||
|
|
||||||
|
// Instead of extern, declare a static pointer in a dedicated section
|
||||||
#[unsafe(no_mangle)]
|
#[unsafe(no_mangle)]
|
||||||
pub unsafe fn call_abi(_call: *const Syscall) {}
|
#[unsafe(link_section = ".user_reloc")]
|
||||||
|
pub static mut call_abi_ptr: usize = 0;
|
||||||
|
|
||||||
|
// Helper to call it
|
||||||
|
pub unsafe fn call_abi(call: *const Syscall) {
|
||||||
|
let f: extern "C" fn(*const Syscall) = unsafe { core::mem::transmute(call_abi_ptr) };
|
||||||
|
f(call);
|
||||||
|
}
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub enum Syscall {
|
pub enum Syscall {
|
||||||
|
|||||||
4
justfile
Normal file
4
justfile
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
kernel: calculator
|
||||||
|
cargo run --bin kernel
|
||||||
|
calculator:
|
||||||
|
RUSTFLAGS="-C link-arg=--noinhibit-exec" cargo build --bin calculator --release
|
||||||
@@ -1,10 +1,10 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "picocalc-os-rs"
|
name = "kernel"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "picocalc-os-rs"
|
name = "kernel"
|
||||||
path = "src/main.rs"
|
path = "src/main.rs"
|
||||||
test = false
|
test = false
|
||||||
doctest = false
|
doctest = false
|
||||||
@@ -78,11 +78,13 @@ static_cell = "2.1.1"
|
|||||||
bitflags = "2.9.1"
|
bitflags = "2.9.1"
|
||||||
heapless = "0.8.0"
|
heapless = "0.8.0"
|
||||||
num_enum = { version = "0.7.4", default-features = false }
|
num_enum = { version = "0.7.4", default-features = false }
|
||||||
goblin = { version = "0.10.0", default-features = false, features = ["elf32", "elf64", "alloc", "endian_fd"] }
|
goblin = { version = "0.10.0", default-features = false, features = [
|
||||||
bumpalo = "3.19.0"
|
"elf32",
|
||||||
|
"elf64",
|
||||||
|
"endian_fd",
|
||||||
|
] }
|
||||||
talc = "4.4.3"
|
talc = "4.4.3"
|
||||||
spin = "0.10.0"
|
spin = "0.10.0"
|
||||||
|
|
||||||
shared = { path = "../shared" }
|
shared = { path = "../shared" }
|
||||||
abi = { path = "../abi" }
|
abi = { path = "../abi" }
|
||||||
|
|
||||||
|
|||||||
@@ -1,22 +1,10 @@
|
|||||||
MEMORY {
|
MEMORY {
|
||||||
/*
|
|
||||||
* The RP2350 has either external or internal flash.
|
|
||||||
*
|
|
||||||
* 2 MiB is a safe default here, although a Pico 2 has 4 MiB.
|
|
||||||
*/
|
|
||||||
FLASH : ORIGIN = 0x10000000, LENGTH = 4096K
|
FLASH : ORIGIN = 0x10000000, LENGTH = 4096K
|
||||||
/*
|
|
||||||
* RAM consists of 8 banks, SRAM0-SRAM7, with a striped mapping.
|
|
||||||
* This is usually good for performance, as it distributes load on
|
|
||||||
* those banks evenly.
|
|
||||||
*/
|
|
||||||
RAM : ORIGIN = 0x20000000, LENGTH = 512K
|
RAM : ORIGIN = 0x20000000, LENGTH = 512K
|
||||||
/*
|
|
||||||
* RAM banks 8 and 9 use a direct mapping. They can be used to have
|
/* Reserve a block of RAM for the user app */
|
||||||
* memory areas dedicated for some specific job, improving predictability
|
USERAPP : ORIGIN = 0x20010000, LENGTH = 192K
|
||||||
* of access times.
|
|
||||||
* Example: Separate stacks for core0 and core1.
|
|
||||||
*/
|
|
||||||
SRAM4 : ORIGIN = 0x20080000, LENGTH = 4K
|
SRAM4 : ORIGIN = 0x20080000, LENGTH = 4K
|
||||||
SRAM5 : ORIGIN = 0x20081000, LENGTH = 4K
|
SRAM5 : ORIGIN = 0x20081000, LENGTH = 4K
|
||||||
}
|
}
|
||||||
@@ -73,3 +61,11 @@ SECTIONS {
|
|||||||
|
|
||||||
PROVIDE(start_to_end = __end_block_addr - __start_block_addr);
|
PROVIDE(start_to_end = __end_block_addr - __start_block_addr);
|
||||||
PROVIDE(end_to_start = __start_block_addr - __end_block_addr);
|
PROVIDE(end_to_start = __start_block_addr - __end_block_addr);
|
||||||
|
|
||||||
|
SECTIONS {
|
||||||
|
.userapp (NOLOAD) :
|
||||||
|
{
|
||||||
|
__userapp_start__ = ORIGIN(USERAPP);
|
||||||
|
__userapp_end__ = ORIGIN(USERAPP) + LENGTH(USERAPP);
|
||||||
|
} > USERAPP
|
||||||
|
}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ use embedded_graphics::{
|
|||||||
use crate::display::FRAMEBUFFER;
|
use crate::display::FRAMEBUFFER;
|
||||||
|
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
pub fn call_abi(call: *const Syscall) {
|
pub extern "C" fn call_abi(call: *const Syscall) {
|
||||||
info!("called abi");
|
info!("called abi");
|
||||||
let call = unsafe { &*call };
|
let call = unsafe { &*call };
|
||||||
match call {
|
match call {
|
||||||
|
|||||||
@@ -1,85 +1,70 @@
|
|||||||
#![allow(static_mut_refs)]
|
#![allow(static_mut_refs)]
|
||||||
use abi::Syscall;
|
|
||||||
use bumpalo::Bump;
|
|
||||||
use core::{alloc::Layout, ffi::c_void, ptr::NonNull, slice::from_raw_parts_mut};
|
use core::{alloc::Layout, ffi::c_void, ptr::NonNull, slice::from_raw_parts_mut};
|
||||||
use goblin::{
|
use goblin::elf::{Elf, header::ET_DYN, program_header::PT_LOAD, sym};
|
||||||
elf::{Elf, header::ET_DYN, program_header::PT_LOAD, sym},
|
|
||||||
elf32,
|
|
||||||
};
|
|
||||||
|
|
||||||
use crate::abi::call_abi;
|
// userland ram region defined in memory.x
|
||||||
|
unsafe extern "C" {
|
||||||
|
static __userapp_start__: u8;
|
||||||
|
static __userapp_end__: u8;
|
||||||
|
}
|
||||||
|
|
||||||
pub fn load_elf(elf_bytes: &[u8], bump: &mut Bump) -> Result<extern "C" fn() -> !, ()> {
|
type EntryFn = extern "C" fn();
|
||||||
let elf = Elf::parse(elf_bytes).map_err(|_| ())?;
|
|
||||||
|
|
||||||
if elf.is_64
|
pub unsafe fn load_binary(bytes: &[u8]) -> Result<EntryFn, &str> {
|
||||||
|| elf.is_lib
|
let elf = Elf::parse(&bytes).expect("Failed to parse ELF");
|
||||||
|| elf.is_object_file()
|
|
||||||
|| !elf.little_endian
|
if elf.is_64 || elf.is_lib || !elf.little_endian {
|
||||||
|| elf.header.e_type != ET_DYN
|
return Err("Unsupported ELF type");
|
||||||
|| elf.interpreter.is_some()
|
|
||||||
{
|
|
||||||
return Err(());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find base address (lowest virtual address of PT_LOAD segments)
|
|
||||||
let base_vaddr = elf
|
|
||||||
.program_headers
|
|
||||||
.iter()
|
|
||||||
.filter(|ph| ph.p_type == PT_LOAD)
|
|
||||||
.map(|ph| ph.p_vaddr)
|
|
||||||
.min()
|
|
||||||
.ok_or(())?;
|
|
||||||
|
|
||||||
// Determine total memory needed for all PT_LOAD segments
|
|
||||||
let total_size = elf
|
|
||||||
.program_headers
|
|
||||||
.iter()
|
|
||||||
.filter(|ph| ph.p_type == PT_LOAD)
|
|
||||||
.map(|ph| {
|
|
||||||
let start = ph.p_vaddr;
|
|
||||||
let end = ph.p_vaddr + ph.p_memsz;
|
|
||||||
end - base_vaddr
|
|
||||||
})
|
|
||||||
.max()
|
|
||||||
.unwrap_or(0) as usize;
|
|
||||||
|
|
||||||
// Allocate one big block from the bump heap
|
|
||||||
let layout = Layout::from_size_align(total_size, 0x1000).map_err(|_| ())?;
|
|
||||||
let base_ptr = bump.alloc_layout(layout).as_ptr();
|
|
||||||
|
|
||||||
for ph in &elf.program_headers {
|
for ph in &elf.program_headers {
|
||||||
if ph.p_type != PT_LOAD {
|
if ph.p_type == PT_LOAD {
|
||||||
continue;
|
let vaddr = ph.p_vaddr as usize;
|
||||||
|
let memsz = ph.p_memsz as usize;
|
||||||
|
let filesz = ph.p_filesz as usize;
|
||||||
|
let offset = ph.p_offset as usize;
|
||||||
|
|
||||||
|
let seg_start = vaddr;
|
||||||
|
let seg_end = vaddr + memsz;
|
||||||
|
|
||||||
|
// Bounds check: make sure segment fits inside payload region
|
||||||
|
let user_start = unsafe { &__userapp_start__ as *const u8 as usize };
|
||||||
|
let user_end = unsafe { &__userapp_end__ as *const u8 as usize };
|
||||||
|
if seg_start < user_start || seg_end > user_end {
|
||||||
|
panic!(
|
||||||
|
"Segment out of bounds: {:x}..{:x} not within {:x}..{:x}",
|
||||||
|
seg_start, seg_end, user_start, user_end
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let file_offset = ph.p_offset as usize;
|
|
||||||
let file_size = ph.p_filesz as usize;
|
|
||||||
let mem_size = ph.p_memsz as usize;
|
|
||||||
let virt_offset = (ph.p_vaddr - base_vaddr) as usize;
|
|
||||||
|
|
||||||
let src = &elf_bytes[file_offset..file_offset + file_size];
|
|
||||||
let dst = unsafe { base_ptr.add(virt_offset) };
|
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
core::ptr::copy_nonoverlapping(src.as_ptr(), dst, file_size);
|
let dst = seg_start as *mut u8;
|
||||||
if mem_size > file_size {
|
let src = bytes.as_ptr().add(offset);
|
||||||
core::ptr::write_bytes(dst.add(file_size), 0, mem_size - file_size);
|
|
||||||
|
// Copy initialized part
|
||||||
|
core::ptr::copy_nonoverlapping(src, dst, filesz);
|
||||||
|
|
||||||
|
// Zero BSS region (memsz - filesz)
|
||||||
|
if memsz > filesz {
|
||||||
|
core::ptr::write_bytes(dst.add(filesz), 0, memsz - filesz);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Patch `call_abi` symbol
|
let call_abi_sym = elf
|
||||||
for sym in elf.syms.iter() {
|
.syms
|
||||||
let name = elf.strtab.get_at(sym.st_name).ok_or(())?;
|
.iter()
|
||||||
if name == "call_abi" && sym.st_bind() == sym::STB_GLOBAL {
|
.find(|s| elf.strtab.get_at(s.st_name).unwrap() == "call_abi_ptr")
|
||||||
let offset = (sym.st_value - base_vaddr) as usize;
|
.expect("call_abi_ptr not found");
|
||||||
let ptr = unsafe { base_ptr.add(offset) as *mut usize };
|
|
||||||
unsafe { *ptr = call_abi as usize };
|
// Virtual address inside user RAM
|
||||||
}
|
let addr = call_abi_sym.st_value as *mut usize;
|
||||||
|
|
||||||
|
// Patch it
|
||||||
|
unsafe {
|
||||||
|
core::ptr::write(addr, crate::abi::call_abi as usize);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compute relocated entry point
|
Ok(unsafe { core::mem::transmute(elf.entry as u32) })
|
||||||
let relocated_entry = unsafe { base_ptr.add((elf.entry - base_vaddr) as usize) };
|
|
||||||
Ok(unsafe { core::mem::transmute(relocated_entry) })
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ mod utils;
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
display::{display_handler, init_display},
|
display::{display_handler, init_display},
|
||||||
elf::load_elf,
|
elf::load_binary,
|
||||||
peripherals::{
|
peripherals::{
|
||||||
conf_peripherals,
|
conf_peripherals,
|
||||||
keyboard::{KeyCode, KeyState, read_keyboard_fifo},
|
keyboard::{KeyCode, KeyState, read_keyboard_fifo},
|
||||||
@@ -26,7 +26,6 @@ use crate::{
|
|||||||
|
|
||||||
use {defmt_rtt as _, panic_probe as _};
|
use {defmt_rtt as _, panic_probe as _};
|
||||||
|
|
||||||
use bumpalo::Bump;
|
|
||||||
use defmt::unwrap;
|
use defmt::unwrap;
|
||||||
use embassy_executor::{Executor, Spawner};
|
use embassy_executor::{Executor, Spawner};
|
||||||
use embassy_futures::join::join;
|
use embassy_futures::join::join;
|
||||||
@@ -56,7 +55,7 @@ static mut CORE1_STACK: Stack<16384> = Stack::new();
|
|||||||
static EXECUTOR0: StaticCell<Executor> = StaticCell::new();
|
static EXECUTOR0: StaticCell<Executor> = StaticCell::new();
|
||||||
static EXECUTOR1: StaticCell<Executor> = StaticCell::new();
|
static EXECUTOR1: StaticCell<Executor> = StaticCell::new();
|
||||||
|
|
||||||
static mut ARENA: [u8; 50_000] = [0; 50_000];
|
static mut ARENA: [u8; 10000] = [0; 10000];
|
||||||
|
|
||||||
#[global_allocator]
|
#[global_allocator]
|
||||||
static ALLOCATOR: Talck<spin::Mutex<()>, ClaimOnOom> =
|
static ALLOCATOR: Talck<spin::Mutex<()>, ClaimOnOom> =
|
||||||
@@ -107,14 +106,14 @@ async fn main(_spawner: Spawner) {
|
|||||||
// runs dynamically loaded elf files
|
// runs dynamically loaded elf files
|
||||||
#[embassy_executor::task]
|
#[embassy_executor::task]
|
||||||
async fn userland_task() {
|
async fn userland_task() {
|
||||||
let mut bump = Bump::with_capacity(25_000);
|
defmt::info!("Loading binary");
|
||||||
|
|
||||||
let binary_data: &[u8] =
|
let binary_data: &[u8] =
|
||||||
include_bytes!("../../target/thumbv8m.main-none-eabihf/debug/calculator");
|
include_bytes!("../../target/thumbv8m.main-none-eabihf/release/calculator");
|
||||||
let entry = load_elf(binary_data, &mut bump).unwrap();
|
|
||||||
|
defmt::info!("Running binary");
|
||||||
|
let entry = unsafe { load_binary(binary_data).unwrap() };
|
||||||
|
|
||||||
entry();
|
entry();
|
||||||
bump.reset(); // clear heap arena
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Display {
|
struct Display {
|
||||||
|
|||||||
28
user-apps/calculator/build.rs
Normal file
28
user-apps/calculator/build.rs
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
//! This build script copies the `memory.x` file from the crate root into
|
||||||
|
//! a directory where the linker can always find it at build time.
|
||||||
|
//! For many projects this is optional, as the linker always searches the
|
||||||
|
//! project root directory -- wherever `Cargo.toml` is. However, if you
|
||||||
|
//! are using a workspace or have a more complicated build setup, this
|
||||||
|
//! build script becomes required. Additionally, by requesting that
|
||||||
|
//! Cargo re-run the build script whenever `memory.x` is changed,
|
||||||
|
//! updating `memory.x` ensures a rebuild of the application with the
|
||||||
|
//! new memory settings.
|
||||||
|
|
||||||
|
use std::env;
|
||||||
|
use std::fs::File;
|
||||||
|
use std::io::Write;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
// Put `memory.x` in our output directory and ensure it's
|
||||||
|
// on the linker search path.
|
||||||
|
let out = &PathBuf::from(env::var_os("OUT_DIR").unwrap());
|
||||||
|
File::create(out.join("memory.x"))
|
||||||
|
.unwrap()
|
||||||
|
.write_all(include_bytes!("../memory.x"))
|
||||||
|
.unwrap();
|
||||||
|
println!("cargo:rustc-link-search={}", out.display());
|
||||||
|
|
||||||
|
println!("cargo:rerun-if-changed=memory.x");
|
||||||
|
println!("cargo:rustc-link-arg-bins=-Tmemory.x");
|
||||||
|
}
|
||||||
@@ -10,8 +10,7 @@ fn panic(_info: &PanicInfo) -> ! {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[unsafe(no_mangle)]
|
#[unsafe(no_mangle)]
|
||||||
pub extern "C" fn _start() -> ! {
|
pub extern "C" fn _start() {
|
||||||
loop {
|
|
||||||
for i in 0..300 {
|
for i in 0..300 {
|
||||||
for o in 0..300 {
|
for o in 0..300 {
|
||||||
let call = Syscall::DrawPixel {
|
let call = Syscall::DrawPixel {
|
||||||
@@ -22,5 +21,4 @@ pub extern "C" fn _start() -> ! {
|
|||||||
unsafe { call_abi(&call) };
|
unsafe { call_abi(&call) };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,21 +0,0 @@
|
|||||||
MEMORY
|
|
||||||
{
|
|
||||||
RAM : ORIGIN = 0x00000000, LENGTH = 256K
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTIONS
|
|
||||||
{
|
|
||||||
.text : {
|
|
||||||
*(.text .text.*);
|
|
||||||
*(.rodata .rodata.*);
|
|
||||||
} > RAM
|
|
||||||
|
|
||||||
.data : {
|
|
||||||
*(.data .data.*);
|
|
||||||
} > RAM
|
|
||||||
|
|
||||||
.bss : {
|
|
||||||
*(.bss .bss.*);
|
|
||||||
*(COMMON);
|
|
||||||
} > RAM
|
|
||||||
}
|
|
||||||
33
user-apps/memory.x
Normal file
33
user-apps/memory.x
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
MEMORY
|
||||||
|
{
|
||||||
|
/* Must match the USERAPP region in the kernel linker script */
|
||||||
|
RAM : ORIGIN = 0x20010000, LENGTH = 192K
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTIONS
|
||||||
|
{
|
||||||
|
/* Reserve first 1KB for patchable symbols */
|
||||||
|
.user_reloc (NOLOAD) : ALIGN(4)
|
||||||
|
{
|
||||||
|
__user_reloc_start = .;
|
||||||
|
KEEP(*(.user_reloc*));
|
||||||
|
__user_reloc_end = .;
|
||||||
|
} > RAM
|
||||||
|
|
||||||
|
.text : ALIGN(4)
|
||||||
|
{
|
||||||
|
*(.text .text.*);
|
||||||
|
*(.rodata .rodata.*);
|
||||||
|
} > RAM
|
||||||
|
|
||||||
|
.data : ALIGN(4)
|
||||||
|
{
|
||||||
|
*(.data .data.*);
|
||||||
|
} > RAM
|
||||||
|
|
||||||
|
.bss : ALIGN(4)
|
||||||
|
{
|
||||||
|
*(.bss .bss.*);
|
||||||
|
*(COMMON);
|
||||||
|
} > RAM
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user