Merge pull request #2933 from embassy-rs/update-stable
Update stable Rust.
This commit is contained in:
commit
b56a0419bd
8 changed files with 276 additions and 81 deletions
|
@ -478,8 +478,12 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn zero_len() {
|
fn zero_len() {
|
||||||
|
let mut b = [0; 0];
|
||||||
|
|
||||||
let rb = RingBuffer::new();
|
let rb = RingBuffer::new();
|
||||||
unsafe {
|
unsafe {
|
||||||
|
rb.init(b.as_mut_ptr(), b.len());
|
||||||
|
|
||||||
assert_eq!(rb.is_empty(), true);
|
assert_eq!(rb.is_empty(), true);
|
||||||
assert_eq!(rb.is_full(), true);
|
assert_eq!(rb.is_full(), true);
|
||||||
|
|
||||||
|
|
|
@ -52,6 +52,7 @@ trait SealedInstance {
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
fn regs() -> crate::pac::adc::Adc;
|
fn regs() -> crate::pac::adc::Adc;
|
||||||
#[cfg(not(any(adc_f1, adc_v1, adc_l0, adc_f3_v2, adc_f3_v1_1, adc_g0)))]
|
#[cfg(not(any(adc_f1, adc_v1, adc_l0, adc_f3_v2, adc_f3_v1_1, adc_g0)))]
|
||||||
|
#[allow(unused)]
|
||||||
fn common_regs() -> crate::pac::adccommon::AdcCommon;
|
fn common_regs() -> crate::pac::adccommon::AdcCommon;
|
||||||
#[cfg(any(adc_f1, adc_f3, adc_v1, adc_l0, adc_f3_v1_1))]
|
#[cfg(any(adc_f1, adc_f3, adc_v1, adc_l0, adc_f3_v1_1))]
|
||||||
fn state() -> &'static State;
|
fn state() -> &'static State;
|
||||||
|
|
|
@ -47,6 +47,7 @@ trait SealedInstance {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Enable global interrupt
|
/// Enable global interrupt
|
||||||
|
#[allow(unused)]
|
||||||
fn enable_irq(&self) {
|
fn enable_irq(&self) {
|
||||||
Self::regs().csr().modify(|v| v.set_ien(true))
|
Self::regs().csr().modify(|v| v.set_ien(true))
|
||||||
}
|
}
|
||||||
|
|
|
@ -969,17 +969,6 @@ fn finish_dma(regs: Regs) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
trait RegsExt {
|
|
||||||
fn dr_ptr<W>(&self) -> *mut W;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl RegsExt for Regs {
|
|
||||||
fn dr_ptr<W>(&self) -> *mut W {
|
|
||||||
let dr = self.dr();
|
|
||||||
dr.as_ptr() as *mut W
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) trait SealedInstance {
|
pub(crate) trait SealedInstance {
|
||||||
const REGS: Regs;
|
const REGS: Regs;
|
||||||
}
|
}
|
||||||
|
|
|
@ -177,9 +177,10 @@ embassy_time_queue_driver::timer_queue_impl!(static QUEUE: Queue = Queue::new())
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
#[cfg(feature = "mock-driver")]
|
#[cfg(feature = "mock-driver")]
|
||||||
mod tests {
|
mod tests {
|
||||||
use core::cell::Cell;
|
use core::sync::atomic::{AtomicBool, Ordering};
|
||||||
use core::task::{RawWaker, RawWakerVTable, Waker};
|
use core::task::Waker;
|
||||||
use std::rc::Rc;
|
use std::sync::Arc;
|
||||||
|
use std::task::Wake;
|
||||||
|
|
||||||
use serial_test::serial;
|
use serial_test::serial;
|
||||||
|
|
||||||
|
@ -188,42 +189,26 @@ mod tests {
|
||||||
use crate::{Duration, Instant};
|
use crate::{Duration, Instant};
|
||||||
|
|
||||||
struct TestWaker {
|
struct TestWaker {
|
||||||
pub awoken: Rc<Cell<bool>>,
|
pub awoken: AtomicBool,
|
||||||
pub waker: Waker,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TestWaker {
|
impl Wake for TestWaker {
|
||||||
fn new() -> Self {
|
fn wake(self: Arc<Self>) {
|
||||||
let flag = Rc::new(Cell::new(false));
|
self.awoken.store(true, Ordering::Relaxed);
|
||||||
|
|
||||||
const VTABLE: RawWakerVTable = RawWakerVTable::new(
|
|
||||||
|data: *const ()| {
|
|
||||||
unsafe {
|
|
||||||
Rc::increment_strong_count(data as *const Cell<bool>);
|
|
||||||
}
|
|
||||||
|
|
||||||
RawWaker::new(data as _, &VTABLE)
|
|
||||||
},
|
|
||||||
|data: *const ()| unsafe {
|
|
||||||
let data = data as *const Cell<bool>;
|
|
||||||
data.as_ref().unwrap().set(true);
|
|
||||||
Rc::decrement_strong_count(data);
|
|
||||||
},
|
|
||||||
|data: *const ()| unsafe {
|
|
||||||
(data as *const Cell<bool>).as_ref().unwrap().set(true);
|
|
||||||
},
|
|
||||||
|data: *const ()| unsafe {
|
|
||||||
Rc::decrement_strong_count(data);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
let raw = RawWaker::new(Rc::into_raw(flag.clone()) as _, &VTABLE);
|
|
||||||
|
|
||||||
Self {
|
|
||||||
awoken: flag.clone(),
|
|
||||||
waker: unsafe { Waker::from_raw(raw) },
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn wake_by_ref(self: &Arc<Self>) {
|
||||||
|
self.awoken.store(true, Ordering::Relaxed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_waker() -> (Arc<TestWaker>, Waker) {
|
||||||
|
let arc = Arc::new(TestWaker {
|
||||||
|
awoken: AtomicBool::new(false),
|
||||||
|
});
|
||||||
|
let waker = Waker::from(arc.clone());
|
||||||
|
|
||||||
|
(arc, waker)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn setup() {
|
fn setup() {
|
||||||
|
@ -249,11 +234,11 @@ mod tests {
|
||||||
|
|
||||||
assert_eq!(queue_len(), 0);
|
assert_eq!(queue_len(), 0);
|
||||||
|
|
||||||
let waker = TestWaker::new();
|
let (flag, waker) = test_waker();
|
||||||
|
|
||||||
QUEUE.schedule_wake(Instant::from_secs(1), &waker.waker);
|
QUEUE.schedule_wake(Instant::from_secs(1), &waker);
|
||||||
|
|
||||||
assert!(!waker.awoken.get());
|
assert!(!flag.awoken.load(Ordering::Relaxed));
|
||||||
assert_eq!(queue_len(), 1);
|
assert_eq!(queue_len(), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -262,23 +247,23 @@ mod tests {
|
||||||
fn test_schedule_same() {
|
fn test_schedule_same() {
|
||||||
setup();
|
setup();
|
||||||
|
|
||||||
let waker = TestWaker::new();
|
let (_flag, waker) = test_waker();
|
||||||
|
|
||||||
QUEUE.schedule_wake(Instant::from_secs(1), &waker.waker);
|
QUEUE.schedule_wake(Instant::from_secs(1), &waker);
|
||||||
|
|
||||||
assert_eq!(queue_len(), 1);
|
assert_eq!(queue_len(), 1);
|
||||||
|
|
||||||
QUEUE.schedule_wake(Instant::from_secs(1), &waker.waker);
|
QUEUE.schedule_wake(Instant::from_secs(1), &waker);
|
||||||
|
|
||||||
assert_eq!(queue_len(), 1);
|
assert_eq!(queue_len(), 1);
|
||||||
|
|
||||||
QUEUE.schedule_wake(Instant::from_secs(100), &waker.waker);
|
QUEUE.schedule_wake(Instant::from_secs(100), &waker);
|
||||||
|
|
||||||
assert_eq!(queue_len(), 1);
|
assert_eq!(queue_len(), 1);
|
||||||
|
|
||||||
let waker2 = TestWaker::new();
|
let (_flag2, waker2) = test_waker();
|
||||||
|
|
||||||
QUEUE.schedule_wake(Instant::from_secs(100), &waker2.waker);
|
QUEUE.schedule_wake(Instant::from_secs(100), &waker2);
|
||||||
|
|
||||||
assert_eq!(queue_len(), 2);
|
assert_eq!(queue_len(), 2);
|
||||||
}
|
}
|
||||||
|
@ -288,21 +273,21 @@ mod tests {
|
||||||
fn test_trigger() {
|
fn test_trigger() {
|
||||||
setup();
|
setup();
|
||||||
|
|
||||||
let waker = TestWaker::new();
|
let (flag, waker) = test_waker();
|
||||||
|
|
||||||
QUEUE.schedule_wake(Instant::from_secs(100), &waker.waker);
|
QUEUE.schedule_wake(Instant::from_secs(100), &waker);
|
||||||
|
|
||||||
assert!(!waker.awoken.get());
|
assert!(!flag.awoken.load(Ordering::Relaxed));
|
||||||
|
|
||||||
MockDriver::get().advance(Duration::from_secs(99));
|
MockDriver::get().advance(Duration::from_secs(99));
|
||||||
|
|
||||||
assert!(!waker.awoken.get());
|
assert!(!flag.awoken.load(Ordering::Relaxed));
|
||||||
|
|
||||||
assert_eq!(queue_len(), 1);
|
assert_eq!(queue_len(), 1);
|
||||||
|
|
||||||
MockDriver::get().advance(Duration::from_secs(1));
|
MockDriver::get().advance(Duration::from_secs(1));
|
||||||
|
|
||||||
assert!(waker.awoken.get());
|
assert!(flag.awoken.load(Ordering::Relaxed));
|
||||||
|
|
||||||
assert_eq!(queue_len(), 0);
|
assert_eq!(queue_len(), 0);
|
||||||
}
|
}
|
||||||
|
@ -312,18 +297,18 @@ mod tests {
|
||||||
fn test_immediate_trigger() {
|
fn test_immediate_trigger() {
|
||||||
setup();
|
setup();
|
||||||
|
|
||||||
let waker = TestWaker::new();
|
let (flag, waker) = test_waker();
|
||||||
|
|
||||||
QUEUE.schedule_wake(Instant::from_secs(100), &waker.waker);
|
QUEUE.schedule_wake(Instant::from_secs(100), &waker);
|
||||||
|
|
||||||
MockDriver::get().advance(Duration::from_secs(50));
|
MockDriver::get().advance(Duration::from_secs(50));
|
||||||
|
|
||||||
let waker2 = TestWaker::new();
|
let (flag2, waker2) = test_waker();
|
||||||
|
|
||||||
QUEUE.schedule_wake(Instant::from_secs(40), &waker2.waker);
|
QUEUE.schedule_wake(Instant::from_secs(40), &waker2);
|
||||||
|
|
||||||
assert!(!waker.awoken.get());
|
assert!(!flag.awoken.load(Ordering::Relaxed));
|
||||||
assert!(waker2.awoken.get());
|
assert!(flag2.awoken.load(Ordering::Relaxed));
|
||||||
assert_eq!(queue_len(), 1);
|
assert_eq!(queue_len(), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -333,30 +318,31 @@ mod tests {
|
||||||
setup();
|
setup();
|
||||||
|
|
||||||
for i in 1..super::QUEUE_SIZE {
|
for i in 1..super::QUEUE_SIZE {
|
||||||
let waker = TestWaker::new();
|
let (flag, waker) = test_waker();
|
||||||
|
|
||||||
QUEUE.schedule_wake(Instant::from_secs(310), &waker.waker);
|
QUEUE.schedule_wake(Instant::from_secs(310), &waker);
|
||||||
|
|
||||||
assert_eq!(queue_len(), i);
|
assert_eq!(queue_len(), i);
|
||||||
assert!(!waker.awoken.get());
|
assert!(!flag.awoken.load(Ordering::Relaxed));
|
||||||
}
|
}
|
||||||
|
|
||||||
let first_waker = TestWaker::new();
|
let (flag, waker) = test_waker();
|
||||||
|
|
||||||
QUEUE.schedule_wake(Instant::from_secs(300), &first_waker.waker);
|
QUEUE.schedule_wake(Instant::from_secs(300), &waker);
|
||||||
|
|
||||||
assert_eq!(queue_len(), super::QUEUE_SIZE);
|
assert_eq!(queue_len(), super::QUEUE_SIZE);
|
||||||
assert!(!first_waker.awoken.get());
|
assert!(!flag.awoken.load(Ordering::Relaxed));
|
||||||
|
|
||||||
let second_waker = TestWaker::new();
|
let (flag2, waker2) = test_waker();
|
||||||
|
|
||||||
QUEUE.schedule_wake(Instant::from_secs(305), &second_waker.waker);
|
QUEUE.schedule_wake(Instant::from_secs(305), &waker2);
|
||||||
|
|
||||||
assert_eq!(queue_len(), super::QUEUE_SIZE);
|
assert_eq!(queue_len(), super::QUEUE_SIZE);
|
||||||
assert!(first_waker.awoken.get());
|
assert!(flag.awoken.load(Ordering::Relaxed));
|
||||||
|
|
||||||
QUEUE.schedule_wake(Instant::from_secs(320), &TestWaker::new().waker);
|
let (_flag3, waker3) = test_waker();
|
||||||
|
QUEUE.schedule_wake(Instant::from_secs(320), &waker3);
|
||||||
assert_eq!(queue_len(), super::QUEUE_SIZE);
|
assert_eq!(queue_len(), super::QUEUE_SIZE);
|
||||||
assert!(second_waker.awoken.get());
|
assert!(flag2.awoken.load(Ordering::Relaxed));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
[toolchain]
|
[toolchain]
|
||||||
channel = "1.77"
|
channel = "1.78"
|
||||||
components = [ "rust-src", "rustfmt", "llvm-tools" ]
|
components = [ "rust-src", "rustfmt", "llvm-tools" ]
|
||||||
targets = [
|
targets = [
|
||||||
"thumbv7em-none-eabi",
|
"thumbv7em-none-eabi",
|
||||||
|
|
|
@ -11,8 +11,8 @@ embassy-executor = { version = "0.5.0", path = "../../embassy-executor", feature
|
||||||
embassy-time = { version = "0.3.0", path = "../../embassy-time" }
|
embassy-time = { version = "0.3.0", path = "../../embassy-time" }
|
||||||
embassy-futures = { version = "0.1.0", path = "../../embassy-futures" }
|
embassy-futures = { version = "0.1.0", path = "../../embassy-futures" }
|
||||||
|
|
||||||
riscv-rt = "0.11"
|
riscv-rt = "0.12.2"
|
||||||
riscv = { version = "0.10", features = ["critical-section-single-hart"] }
|
riscv = { version = "0.11.1", features = ["critical-section-single-hart"] }
|
||||||
|
|
||||||
|
|
||||||
[profile.dev]
|
[profile.dev]
|
||||||
|
|
214
tests/riscv32/link.x
Normal file
214
tests/riscv32/link.x
Normal file
|
@ -0,0 +1,214 @@
|
||||||
|
/* # EMBASSY notes
|
||||||
|
This file is a workaround for https://github.com/rust-embedded/riscv/issues/196
|
||||||
|
Remove when fixed upstream.
|
||||||
|
*/
|
||||||
|
/* # Developer notes
|
||||||
|
|
||||||
|
- Symbols that start with a double underscore (__) are considered "private"
|
||||||
|
|
||||||
|
- Symbols that start with a single underscore (_) are considered "semi-public"; they can be
|
||||||
|
overridden in a user linker script, but should not be referred from user code (e.g. `extern "C" {
|
||||||
|
static mut _heap_size }`).
|
||||||
|
|
||||||
|
- `EXTERN` forces the linker to keep a symbol in the final binary. We use this to make sure a
|
||||||
|
symbol if not dropped if it appears in or near the front of the linker arguments and "it's not
|
||||||
|
needed" by any of the preceding objects (linker arguments)
|
||||||
|
|
||||||
|
- `PROVIDE` is used to provide default values that can be overridden by a user linker script
|
||||||
|
|
||||||
|
- In this linker script, you may find symbols that look like `${...}` (e.g., `4`).
|
||||||
|
These are wildcards used by the `build.rs` script to adapt to different target particularities.
|
||||||
|
Check `build.rs` for more details about these symbols.
|
||||||
|
|
||||||
|
- On alignment: it's important for correctness that the VMA boundaries of both .bss and .data *and*
|
||||||
|
the LMA of .data are all `4`-byte aligned. These alignments are assumed by the RAM
|
||||||
|
initialization routine. There's also a second benefit: `4`-byte aligned boundaries
|
||||||
|
means that you won't see "Address (..) is out of bounds" in the disassembly produced by `objdump`.
|
||||||
|
*/
|
||||||
|
|
||||||
|
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(InstructionMisaligned = ExceptionHandler);
|
||||||
|
PROVIDE(InstructionFault = ExceptionHandler);
|
||||||
|
PROVIDE(IllegalInstruction = ExceptionHandler);
|
||||||
|
PROVIDE(Breakpoint = ExceptionHandler);
|
||||||
|
PROVIDE(LoadMisaligned = ExceptionHandler);
|
||||||
|
PROVIDE(LoadFault = ExceptionHandler);
|
||||||
|
PROVIDE(StoreMisaligned = ExceptionHandler);
|
||||||
|
PROVIDE(StoreFault = ExceptionHandler);;
|
||||||
|
PROVIDE(UserEnvCall = ExceptionHandler);
|
||||||
|
PROVIDE(SupervisorEnvCall = ExceptionHandler);
|
||||||
|
PROVIDE(MachineEnvCall = ExceptionHandler);
|
||||||
|
PROVIDE(InstructionPageFault = ExceptionHandler);
|
||||||
|
PROVIDE(LoadPageFault = ExceptionHandler);
|
||||||
|
PROVIDE(StorePageFault = ExceptionHandler);
|
||||||
|
|
||||||
|
PROVIDE(SupervisorSoft = DefaultHandler);
|
||||||
|
PROVIDE(MachineSoft = DefaultHandler);
|
||||||
|
PROVIDE(SupervisorTimer = DefaultHandler);
|
||||||
|
PROVIDE(MachineTimer = DefaultHandler);
|
||||||
|
PROVIDE(SupervisorExternal = DefaultHandler);
|
||||||
|
PROVIDE(MachineExternal = DefaultHandler);
|
||||||
|
|
||||||
|
PROVIDE(DefaultHandler = DefaultInterruptHandler);
|
||||||
|
PROVIDE(ExceptionHandler = DefaultExceptionHandler);
|
||||||
|
|
||||||
|
/* # Pre-initialization function */
|
||||||
|
/* If the user overrides this using the `#[pre_init]` attribute or by creating a `__pre_init` function,
|
||||||
|
then the function this points to will be called before the RAM is initialized. */
|
||||||
|
PROVIDE(__pre_init = default_pre_init);
|
||||||
|
|
||||||
|
/* A PAC/HAL defined routine that should initialize custom interrupt controller if needed. */
|
||||||
|
PROVIDE(_setup_interrupts = default_setup_interrupts);
|
||||||
|
|
||||||
|
/* # Multi-processing hook function
|
||||||
|
fn _mp_hook() -> bool;
|
||||||
|
|
||||||
|
This function is called from all the harts and must return true only for one hart,
|
||||||
|
which will perform memory initialization. For other harts it must return false
|
||||||
|
and implement wake-up in platform-dependent way (e.g. after waiting for a user interrupt).
|
||||||
|
*/
|
||||||
|
PROVIDE(_mp_hook = default_mp_hook);
|
||||||
|
|
||||||
|
/* # Start trap function override
|
||||||
|
By default uses the riscv crates default trap handler
|
||||||
|
but by providing the `_start_trap` symbol external crates can override.
|
||||||
|
*/
|
||||||
|
PROVIDE(_start_trap = default_start_trap);
|
||||||
|
|
||||||
|
SECTIONS
|
||||||
|
{
|
||||||
|
.text.dummy (NOLOAD) :
|
||||||
|
{
|
||||||
|
/* This section is intended to make _stext address work */
|
||||||
|
. = ABSOLUTE(_stext);
|
||||||
|
} > REGION_TEXT
|
||||||
|
|
||||||
|
.text _stext :
|
||||||
|
{
|
||||||
|
/* Put reset handler first in .text section so it ends up as the entry */
|
||||||
|
/* point of the program. */
|
||||||
|
KEEP(*(.init));
|
||||||
|
KEEP(*(.init.rust));
|
||||||
|
. = ALIGN(4);
|
||||||
|
*(.trap);
|
||||||
|
*(.trap.rust);
|
||||||
|
*(.text.abort);
|
||||||
|
*(.text .text.*);
|
||||||
|
} > REGION_TEXT
|
||||||
|
|
||||||
|
.eh_frame : { KEEP(*(.eh_frame)) } > REGION_TEXT
|
||||||
|
.eh_frame_hdr : { *(.eh_frame_hdr) } > REGION_TEXT
|
||||||
|
|
||||||
|
.rodata : ALIGN(4)
|
||||||
|
{
|
||||||
|
*(.srodata .srodata.*);
|
||||||
|
*(.rodata .rodata.*);
|
||||||
|
|
||||||
|
/* 4-byte align the end (VMA) of this section.
|
||||||
|
This is required by LLD to ensure the LMA of the following .data
|
||||||
|
section will have the correct alignment. */
|
||||||
|
. = ALIGN(4);
|
||||||
|
} > REGION_RODATA
|
||||||
|
|
||||||
|
.data : ALIGN(4)
|
||||||
|
{
|
||||||
|
_sidata = LOADADDR(.data);
|
||||||
|
_sdata = .;
|
||||||
|
/* Must be called __global_pointer$ for linker relaxations to work. */
|
||||||
|
PROVIDE(__global_pointer$ = . + 0x800);
|
||||||
|
*(.sdata .sdata.* .sdata2 .sdata2.*);
|
||||||
|
*(.data .data.*);
|
||||||
|
. = ALIGN(4);
|
||||||
|
_edata = .;
|
||||||
|
} > REGION_DATA AT > REGION_RODATA
|
||||||
|
|
||||||
|
.bss (NOLOAD) : ALIGN(4)
|
||||||
|
{
|
||||||
|
_sbss = .;
|
||||||
|
*(.sbss .sbss.* .bss .bss.*);
|
||||||
|
. = ALIGN(4);
|
||||||
|
_ebss = .;
|
||||||
|
} > 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) :
|
||||||
|
{
|
||||||
|
_estack = .;
|
||||||
|
. = ABSOLUTE(_stack_start);
|
||||||
|
_sstack = .;
|
||||||
|
} > REGION_STACK
|
||||||
|
|
||||||
|
/* fake output .got section */
|
||||||
|
/* Dynamic relocations are unsupported. This section is only used to detect
|
||||||
|
relocatable code in the input files and raise an error if relocatable code
|
||||||
|
is found */
|
||||||
|
.got (INFO) :
|
||||||
|
{
|
||||||
|
KEEP(*(.got .got.*));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Do not exceed this mark in the error messages above | */
|
||||||
|
ASSERT(ORIGIN(REGION_TEXT) % 4 == 0, "
|
||||||
|
ERROR(riscv-rt): the start of the REGION_TEXT must be 4-byte aligned");
|
||||||
|
|
||||||
|
ASSERT(ORIGIN(REGION_RODATA) % 4 == 0, "
|
||||||
|
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");
|
||||||
|
|
||||||
|
ASSERT(ORIGIN(REGION_STACK) % 4 == 0, "
|
||||||
|
ERROR(riscv-rt): the start of the REGION_STACK must be 4-byte aligned");
|
||||||
|
|
||||||
|
ASSERT(_stext % 4 == 0, "
|
||||||
|
ERROR(riscv-rt): `_stext` must be 4-byte aligned");
|
||||||
|
|
||||||
|
ASSERT(_sdata % 4 == 0 && _edata % 4 == 0, "
|
||||||
|
BUG(riscv-rt): .data is not 4-byte aligned");
|
||||||
|
|
||||||
|
ASSERT(_sidata % 4 == 0, "
|
||||||
|
BUG(riscv-rt): the LMA of .data is not 4-byte aligned");
|
||||||
|
|
||||||
|
ASSERT(_sbss % 4 == 0 && _ebss % 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
|
||||||
|
then modify your build script to compile the C code _without_ the
|
||||||
|
-fPIC flag. See the documentation of the `gcc::Config.fpic` method for
|
||||||
|
details.");
|
||||||
|
|
||||||
|
/* Do not exceed this mark in the error messages above | */
|
Loading…
Add table
Reference in a new issue