mirror of
https://github.com/embassy-rs/embassy.git
synced 2024-11-25 08:12:30 +00:00
Merge pull request #2933 from embassy-rs/update-stable
Update stable Rust.
This commit is contained in:
commit
b56a0419bd
@ -478,8 +478,12 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn zero_len() {
|
||||
let mut b = [0; 0];
|
||||
|
||||
let rb = RingBuffer::new();
|
||||
unsafe {
|
||||
rb.init(b.as_mut_ptr(), b.len());
|
||||
|
||||
assert_eq!(rb.is_empty(), true);
|
||||
assert_eq!(rb.is_full(), true);
|
||||
|
||||
|
@ -52,6 +52,7 @@ trait SealedInstance {
|
||||
#[allow(unused)]
|
||||
fn regs() -> crate::pac::adc::Adc;
|
||||
#[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;
|
||||
#[cfg(any(adc_f1, adc_f3, adc_v1, adc_l0, adc_f3_v1_1))]
|
||||
fn state() -> &'static State;
|
||||
|
@ -47,6 +47,7 @@ trait SealedInstance {
|
||||
}
|
||||
|
||||
/// Enable global interrupt
|
||||
#[allow(unused)]
|
||||
fn enable_irq(&self) {
|
||||
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 {
|
||||
const REGS: Regs;
|
||||
}
|
||||
|
@ -177,9 +177,10 @@ embassy_time_queue_driver::timer_queue_impl!(static QUEUE: Queue = Queue::new())
|
||||
#[cfg(test)]
|
||||
#[cfg(feature = "mock-driver")]
|
||||
mod tests {
|
||||
use core::cell::Cell;
|
||||
use core::task::{RawWaker, RawWakerVTable, Waker};
|
||||
use std::rc::Rc;
|
||||
use core::sync::atomic::{AtomicBool, Ordering};
|
||||
use core::task::Waker;
|
||||
use std::sync::Arc;
|
||||
use std::task::Wake;
|
||||
|
||||
use serial_test::serial;
|
||||
|
||||
@ -188,42 +189,26 @@ mod tests {
|
||||
use crate::{Duration, Instant};
|
||||
|
||||
struct TestWaker {
|
||||
pub awoken: Rc<Cell<bool>>,
|
||||
pub waker: Waker,
|
||||
pub awoken: AtomicBool,
|
||||
}
|
||||
|
||||
impl TestWaker {
|
||||
fn new() -> Self {
|
||||
let flag = Rc::new(Cell::new(false));
|
||||
|
||||
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) },
|
||||
}
|
||||
impl Wake for TestWaker {
|
||||
fn wake(self: Arc<Self>) {
|
||||
self.awoken.store(true, Ordering::Relaxed);
|
||||
}
|
||||
|
||||
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() {
|
||||
@ -249,11 +234,11 @@ mod tests {
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@ -262,23 +247,23 @@ mod tests {
|
||||
fn test_schedule_same() {
|
||||
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);
|
||||
|
||||
QUEUE.schedule_wake(Instant::from_secs(1), &waker.waker);
|
||||
QUEUE.schedule_wake(Instant::from_secs(1), &waker);
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
}
|
||||
@ -288,21 +273,21 @@ mod tests {
|
||||
fn test_trigger() {
|
||||
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));
|
||||
|
||||
assert!(!waker.awoken.get());
|
||||
assert!(!flag.awoken.load(Ordering::Relaxed));
|
||||
|
||||
assert_eq!(queue_len(), 1);
|
||||
|
||||
MockDriver::get().advance(Duration::from_secs(1));
|
||||
|
||||
assert!(waker.awoken.get());
|
||||
assert!(flag.awoken.load(Ordering::Relaxed));
|
||||
|
||||
assert_eq!(queue_len(), 0);
|
||||
}
|
||||
@ -312,18 +297,18 @@ mod tests {
|
||||
fn test_immediate_trigger() {
|
||||
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));
|
||||
|
||||
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!(waker2.awoken.get());
|
||||
assert!(!flag.awoken.load(Ordering::Relaxed));
|
||||
assert!(flag2.awoken.load(Ordering::Relaxed));
|
||||
assert_eq!(queue_len(), 1);
|
||||
}
|
||||
|
||||
@ -333,30 +318,31 @@ mod tests {
|
||||
setup();
|
||||
|
||||
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!(!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!(!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!(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!(second_waker.awoken.get());
|
||||
assert!(flag2.awoken.load(Ordering::Relaxed));
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
[toolchain]
|
||||
channel = "1.77"
|
||||
channel = "1.78"
|
||||
components = [ "rust-src", "rustfmt", "llvm-tools" ]
|
||||
targets = [
|
||||
"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-futures = { version = "0.1.0", path = "../../embassy-futures" }
|
||||
|
||||
riscv-rt = "0.11"
|
||||
riscv = { version = "0.10", features = ["critical-section-single-hart"] }
|
||||
riscv-rt = "0.12.2"
|
||||
riscv = { version = "0.11.1", features = ["critical-section-single-hart"] }
|
||||
|
||||
|
||||
[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…
Reference in New Issue
Block a user