428: executor: Use critical sections instead of atomic CAS loops r=lulf a=Dirbaio
Optimize executor wakes.
CAS loops (either `fetch_update`, or manual `load + compare_exchange_weak`) generate surprisingly horrible code: https://godbolt.org/z/zhscnM1cb
This switches to using critical sections, which makes it faster. On thumbv6 (Cortex-M0) it should make it even faster, as it is currently using `atomic-polyfill`, which will make many critical sections for each `compare_exchange_weak` anyway.
```
opt-level=3 opt-level=s
atmics: 105 cycles 101 cycles
CS: 76 cycles 72 cycles
CS+inline: 72 cycles 64 cycles
```
Measured in nrf52 with icache disabled, with this code:
```rust
poll_fn(|cx| {
let task = unsafe { task_from_waker(cx.waker()) };
compiler_fence(Ordering::SeqCst);
let a = cortex_m::peripheral::DWT::get_cycle_count();
compiler_fence(Ordering::SeqCst);
unsafe { wake_task(task) }
compiler_fence(Ordering::SeqCst);
let b = cortex_m::peripheral::DWT::get_cycle_count();
compiler_fence(Ordering::SeqCst);
defmt::info!("cycles: {=u32}", b.wrapping_sub(a));
Poll::Ready(())
})
.await;
````
Co-authored-by: Dario Nieuwenhuis <dirbaio@dirbaio.net>
435: Optimises the buffer passing for nRF SAADC r=huntc a=huntc
The buffer will always have been filled and we never explicitly stop the task outside of this code. Thus, we can assume the number of bytes in the slice.
Co-authored-by: huntc <huntchr@gmail.com>
The buffer will always have been filled and we never explicitly stop the task outside of this code. Thus, we can assume the number of bytes in the slice.
425: Implements continuous sampling for the nRF SAADC r=huntc a=huntc
Implements continuous sampling for the nRF SAADC and also renames `OneShot` to `Saadc`. The one-shot behaviour is retained with the `sample` method and a new `run_sampler` method is provided for efficiently (i.e. zero copying) sampler processing. A double buffer is used for continuously sampling, which is swapped appropriately.
A sample frequency is provided and will set the internal timer of the SAADC when there is just one channel being sampled. Otherwise, PPI will be used to hook up the TIMER peripheral to drive the sampling task. Two methods are provided for this: `run_task_sampler` and `run_task_sampler` with the latter available where the compiler sees that just one channel is configured. Note that we set up the PPI and timer behaviour outside of the `Saadc` for maximum flexibility.
A callback is provided to the `run_sampler` method. This is a synchronous callback that should return in a reasonably short space of time. The SAADC could stall if it does not. A reasonable practice is to perform a small amount of processing within the callback to yield a signal, perhaps via `mpsc`. In the case of `mpsc`, the `try_send` method becomes useful.
A new example has been provided to illustrate continuous sampling, along with multiple channels and external timing:
```rust
#[embassy::main]
async fn main(_spawner: Spawner, mut p: Peripherals) {
let config = Config::default();
let channel_1_config = ChannelConfig::single_ended(&mut p.P0_02);
let channel_2_config = ChannelConfig::single_ended(&mut p.P0_03);
let channel_3_config = ChannelConfig::single_ended(&mut p.P0_04);
let mut saadc = Saadc::new(
p.SAADC,
interrupt::take!(SAADC),
config,
[channel_1_config, channel_2_config, channel_3_config],
);
let mut timer = Timer::new(p.TIMER0);
timer.set_frequency(Frequency::F1MHz);
timer.cc(0).write(100); // We want to sample at 10KHz
timer.cc(0).short_compare_clear();
let mut ppi = Ppi::new(p.PPI_CH0);
ppi.set_event(timer.cc(0).event_compare());
ppi.set_task(saadc.task_sample());
ppi.enable();
timer.start();
let mut bufs = [[[0; 3]; 50]; 2];
let mut c = 0;
let mut a: i32 = 0;
saadc
.run_task_sampler(&mut bufs, move |buf| {
for b in buf {
a += b[0] as i32;
}
c += buf.len();
if c > 10000 {
a = a / c as i32;
info!("channel 1: {=i32}", a);
c = 0;
a = 0;
}
SamplerState::Sampled
})
.await;
}
```
Co-authored-by: huntc <huntchr@gmail.com>
Implements continuous sampling for the nRF SAADC and also renames `OneShot` to `Saadc`. The one-shot behaviour is retained with the `sample` method and a new `run_sampler` method is provided for efficiently (i.e. zero copying) sampler processing. A double buffer is used for continuously sampling, which wlll be swapped once sampling has taken place.
A sample frequency is provided and will set the internal timer of the SAADC when there is just the one channel being sampled. Otherwise, PPI will be used to hook up the TIMER peripheral to drive the sampling task.
434: Clippy fixes r=Dirbaio a=Dirbaio
Fixes most clippy lints.
Added `#![allow(clippy::new_without_default)]` because I really, really don't agree with `new()` being the same as `default()`...
Co-authored-by: Dario Nieuwenhuis <dirbaio@dirbaio.net>
429: nrf/uarte: do not use WFE on drop. r=Dirbaio a=Dirbaio
- It disturbs other stuff that uses WFE/SEV in the system. I ran into issues with this.
- It needs the irq handler to check for RXTO/TXSTOPPED errors, which makes it slower.
431: interrupt: transmute instead of steal. r=Dirbaio a=Dirbaio
That steal method has a TAKEN=true write [here](6b013138b7/src/peripheral/mod.rs (L180)).
This is not zero cost, we don't want it. Transmute instead, which is zero cost.
Co-authored-by: Dario Nieuwenhuis <dirbaio@dirbaio.net>
That steal method has a TAKEN=true write [here](6b013138b7/src/peripheral/mod.rs (L180)).
This is not zero cost, we don't want it. Transmute instead, which is zero cost.
- It disturbs other stuff that uses WFE/SEV in the system. I ran into
issues with this.
- It needs the irq handler to check for RXTO/TXSTOPPED errors, which makes
it slower.
423: nRF9160 support r=Dirbaio a=diondokter
- Created a chip file with all the peripherals, interrupts and peripheral implementations.
- All peripherals now use an alias for the NS (non-secure) version of the nRF9160 version.
- Implementations of peripherals that don't exist are ignored.
- Most PPI functionality has been stubbed out because the nRF91 has the newer DPPI which is not compatible with the current API. (The channels are also set to not configurable, so they are kinda useless now, but in principle the stubs should never be called)
Co-authored-by: Dion Dokter <dion@tweedegolf.com>