Compare commits

...

10 Commits

Author SHA1 Message Date
ca3891bb8c executor: remove arch-xtensa.
It's been broken for months and nobody has noticed. The `esp*-hal` crates have
much better support.

Fixes #2234
Closes  #1912
2023-12-03 22:33:27 +01:00
9ba3aeada4 Merge pull request #2243 from peter9477/nrf52-approtect-fix
minimum build code for new APPROTECT is chip type-specific
2023-12-03 20:27:02 +00:00
dd62bb16e5 minimum build code for new APPROTECT is chip type-specific 2023-12-03 13:47:26 -05:00
a31ae52d1a Merge pull request #2240 from GrantM11235/fix-freq-off-by-one
stm32/timer: Fix frequency off-by-one
2023-12-02 08:13:50 +00:00
8c0e2748db stm32/timer: Fix frequency off-by-one 2023-12-01 22:09:15 -06:00
ce4dd67f3b Merge pull request #2236 from tshepang/patch-2
no_std and no_main can be used on stable
2023-12-01 18:10:27 +01:00
929fd551de Merge pull request #2235 from tshepang/patch-1
runtime.adoc: typo
2023-12-01 18:10:15 +01:00
33cfef871d no_std and no_main can be used on stable 2023-12-01 11:56:35 +02:00
270504d87d runtime.adoc: typo 2023-12-01 08:45:20 +02:00
fe8c46bce3 Merge pull request #2218 from embassy-rs/stable2
Remove nightly and unstable-traits features in preparation for 1.75.
2023-11-29 17:50:09 +01:00
15 changed files with 32 additions and 100 deletions

View File

@ -6,13 +6,22 @@ So you've got one of the xref:examples.adoc[examples] running, but what now? Let
The full example can be found link:https://github.com/embassy-rs/embassy/tree/master/docs/modules/ROOT/examples/basic[here].
=== Rust Nightly
=== Bare metal
The first thing you'll notice is a few declarations stating that Embassy requires some nightly features:
The first thing you'll notice is a few declarations, two of which indicate that Embassy is suitable for bare metal development:
[source,rust]
----
include::example$basic/src/main.rs[lines="1..3"]
include::example$basic/src/main.rs[lines="1..2"]
----
=== Rust Nightly
The next declaration is a Rust Unstable feature, which means that Embassy requires Rust Nightly:
[source,rust]
----
include::example$basic/src/main.rs[lines="3"]
----
=== Dealing with errors

View File

@ -27,7 +27,7 @@ If you use the `#[embassy_executor::main]` macro in your application, it creates
Interrupts are a common way for peripherals to signal completion of some operation and fits well with the async execution model. The following diagram describes a typical application flow where (1) a task is polled and is attempting to make progress. The task then (2) instructs the peripheral to perform some operation, and awaits. After some time has passed, (3) an interrupt is raised, marking the completion of the operation.
The peripheral HAL then (4) ensures that interrupt signals are routed to to the peripheral and updating the peripheral state with the results of the operation. The executor is then (5) notified that the task should be polled, which it will do.
The peripheral HAL then (4) ensures that interrupt signals are routed to the peripheral and updating the peripheral state with the results of the operation. The executor is then (5) notified that the task should be polled, which it will do.
image::embassy_irq.png[Interrupt handling]

View File

@ -5,6 +5,10 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## Unreleased
- Removed `arch-xtensa`. Use the executor provided by the HAL crate (`esp-hal`, `esp32s3-hal`, etc...) instead.
## 0.3.3 - 2023-11-15
- Add `main` macro reexport for Xtensa arch.

View File

@ -57,7 +57,6 @@ critical-section = { version = "1.1", features = ["std"] }
_arch = [] # some arch was picked
arch-std = ["_arch", "critical-section/std"]
arch-cortex-m = ["_arch", "dep:cortex-m"]
arch-xtensa = ["_arch"]
arch-riscv32 = ["_arch", "dep:portable-atomic"]
arch-wasm = ["_arch", "dep:wasm-bindgen", "dep:js-sys"]

View File

@ -1,89 +0,0 @@
#[cfg(feature = "executor-interrupt")]
compile_error!("`executor-interrupt` is not supported with `arch-xtensa`.");
#[cfg(feature = "executor-thread")]
pub use thread::*;
#[cfg(feature = "executor-thread")]
mod thread {
use core::marker::PhantomData;
use core::sync::atomic::{AtomicBool, Ordering};
pub use embassy_macros::main_riscv as main;
use crate::{raw, Spawner};
/// global atomic used to keep track of whether there is work to do since sev() is not available on Xtensa
static SIGNAL_WORK_THREAD_MODE: AtomicBool = AtomicBool::new(false);
#[export_name = "__pender"]
fn __pender(_context: *mut ()) {
SIGNAL_WORK_THREAD_MODE.store(true, Ordering::SeqCst);
}
/// Xtensa Executor
pub struct Executor {
inner: raw::Executor,
not_send: PhantomData<*mut ()>,
}
impl Executor {
/// Create a new Executor.
pub fn new() -> Self {
Self {
inner: raw::Executor::new(core::ptr::null_mut()),
not_send: PhantomData,
}
}
/// Run the executor.
///
/// The `init` closure is called with a [`Spawner`] that spawns tasks on
/// this executor. Use it to spawn the initial task(s). After `init` returns,
/// the executor starts running the tasks.
///
/// To spawn more tasks later, you may keep copies of the [`Spawner`] (it is `Copy`),
/// for example by passing it as an argument to the initial tasks.
///
/// This function requires `&'static mut self`. This means you have to store the
/// Executor instance in a place where it'll live forever and grants you mutable
/// access. There's a few ways to do this:
///
/// - a [StaticCell](https://docs.rs/static_cell/latest/static_cell/) (safe)
/// - a `static mut` (unsafe)
/// - a local variable in a function you know never returns (like `fn main() -> !`), upgrading its lifetime with `transmute`. (unsafe)
///
/// This function never returns.
pub fn run(&'static mut self, init: impl FnOnce(Spawner)) -> ! {
init(self.inner.spawner());
loop {
unsafe {
self.inner.poll();
// Manual critical section implementation that only masks interrupts handlers.
// We must not acquire the cross-core on dual-core systems because that would
// prevent the other core from doing useful work while this core is sleeping.
let token: critical_section::RawRestoreState;
core::arch::asm!("rsil {0}, 5", out(reg) token);
// we do not care about race conditions between the load and store operations, interrupts
// will only set this value to true.
// if there is work to do, loop back to polling
if SIGNAL_WORK_THREAD_MODE.load(Ordering::SeqCst) {
SIGNAL_WORK_THREAD_MODE.store(false, Ordering::SeqCst);
core::arch::asm!(
"wsr.ps {0}",
"rsync", in(reg) token)
} else {
// waiti sets the PS.INTLEVEL when slipping into sleep
// because critical sections in Xtensa are implemented via increasing
// PS.INTLEVEL the critical section ends here
// take care not add code after `waiti` if it needs to be inside the CS
core::arch::asm!("waiti 0"); // critical section ends here
}
}
}
}
}
}

View File

@ -1,5 +1,4 @@
#![cfg_attr(not(any(feature = "arch-std", feature = "arch-wasm")), no_std)]
#![cfg_attr(feature = "arch-xtensa", feature(asm_experimental_arch))]
#![allow(clippy::new_without_default)]
#![doc = include_str!("../README.md")]
#![warn(missing_docs)]
@ -21,12 +20,11 @@ macro_rules! check_at_most_one {
check_at_most_one!(@amo [$($f)*] [$($f)*] []);
};
}
check_at_most_one!("arch-cortex-m", "arch-riscv32", "arch-xtensa", "arch-std", "arch-wasm",);
check_at_most_one!("arch-cortex-m", "arch-riscv32", "arch-std", "arch-wasm",);
#[cfg(feature = "_arch")]
#[cfg_attr(feature = "arch-cortex-m", path = "arch/cortex_m.rs")]
#[cfg_attr(feature = "arch-riscv32", path = "arch/riscv32.rs")]
#[cfg_attr(feature = "arch-xtensa", path = "arch/xtensa.rs")]
#[cfg_attr(feature = "arch-std", path = "arch/std.rs")]
#[cfg_attr(feature = "arch-wasm", path = "arch/wasm.rs")]
mod arch;

View File

@ -7,6 +7,7 @@ pub const FORCE_COPY_BUFFER_SIZE: usize = 256;
pub const FLASH_SIZE: usize = 192 * 1024;
pub const RESET_PIN: u32 = 21;
pub const APPROTECT_MIN_BUILD_CODE: u8 = b'B';
embassy_hal_internal::peripherals! {
// RTC

View File

@ -7,6 +7,7 @@ pub const FORCE_COPY_BUFFER_SIZE: usize = 256;
pub const FLASH_SIZE: usize = 192 * 1024;
pub const RESET_PIN: u32 = 21;
pub const APPROTECT_MIN_BUILD_CODE: u8 = b'E';
embassy_hal_internal::peripherals! {
// RTC

View File

@ -7,6 +7,7 @@ pub const FORCE_COPY_BUFFER_SIZE: usize = 256;
pub const FLASH_SIZE: usize = 192 * 1024;
pub const RESET_PIN: u32 = 21;
pub const APPROTECT_MIN_BUILD_CODE: u8 = b'B';
embassy_hal_internal::peripherals! {
// RTC

View File

@ -7,6 +7,7 @@ pub const FORCE_COPY_BUFFER_SIZE: usize = 512;
pub const FLASH_SIZE: usize = 256 * 1024;
pub const RESET_PIN: u32 = 18;
pub const APPROTECT_MIN_BUILD_CODE: u8 = b'D';
embassy_hal_internal::peripherals! {
// USB

View File

@ -11,6 +11,7 @@ pub const FORCE_COPY_BUFFER_SIZE: usize = 255;
pub const FLASH_SIZE: usize = 512 * 1024;
pub const RESET_PIN: u32 = 21;
pub const APPROTECT_MIN_BUILD_CODE: u8 = b'G';
embassy_hal_internal::peripherals! {
// RTC

View File

@ -7,6 +7,7 @@ pub const FORCE_COPY_BUFFER_SIZE: usize = 512;
pub const FLASH_SIZE: usize = 512 * 1024;
pub const RESET_PIN: u32 = 18;
pub const APPROTECT_MIN_BUILD_CODE: u8 = b'B';
embassy_hal_internal::peripherals! {
// USB

View File

@ -7,6 +7,7 @@ pub const FORCE_COPY_BUFFER_SIZE: usize = 512;
pub const FLASH_SIZE: usize = 1024 * 1024;
pub const RESET_PIN: u32 = 18;
pub const APPROTECT_MIN_BUILD_CODE: u8 = b'F';
embassy_hal_internal::peripherals! {
// USB

View File

@ -349,10 +349,11 @@ pub fn init(config: config::Config) -> Peripherals {
// Get the letter for the build code (b'A' .. b'F')
let build_code = (variant >> 8) as u8;
if build_code >= b'F' {
// Chips with build code F and higher (revision 3 and higher) have an
if build_code >= chip::APPROTECT_MIN_BUILD_CODE {
// Chips with a certain chip type-specific build code or higher have an
// improved APPROTECT ("hardware and software controlled access port protection")
// which needs explicit action by the firmware to keep it unlocked
// See https://devzone.nordicsemi.com/nordic/nordic-blog/b/blog/posts/working-with-the-nrf52-series-improved-approtect
// UICR.APPROTECT = SwDisabled
let res = uicr_write(consts::UICR_APPROTECT, consts::APPROTECT_DISABLED);

View File

@ -46,7 +46,10 @@ pub(crate) mod sealed {
assert!(f > 0);
let pclk_ticks_per_timer_period = timer_f / f;
let psc: u16 = unwrap!(((pclk_ticks_per_timer_period - 1) / (1 << 16)).try_into());
let arr: u16 = unwrap!((pclk_ticks_per_timer_period / (u32::from(psc) + 1)).try_into());
let divide_by = pclk_ticks_per_timer_period / (u32::from(psc) + 1);
// the timer counts `0..=arr`, we want it to count `0..divide_by`
let arr = unwrap!(u16::try_from(divide_by - 1));
let regs = Self::regs();
regs.psc().write(|r| r.set_psc(psc));