Skip to content

Commit 298401d

Browse files
committed
Merge remote-tracking branch 'upstream/main' into dpi_driver
2 parents 00dbdd2 + 448ed9a commit 298401d

File tree

40 files changed

+3006
-1732
lines changed

40 files changed

+3006
-1732
lines changed

documentation/API-GUIDELINES.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,15 +28,14 @@ The following paragraphs contain additional recommendations.
2828

2929
## API Surface
3030

31-
- Add `#[deny(missing_docs)]` to new modules or when reworking a larger part of a module. In the end we will require this for whole crates.
32-
- API documentation shouldn't be an afterthought
31+
- API documentation shouldn't be an afterthought.
3332
- Private details shouldn't leak into the public API, and should be made private where technically possible.
34-
- Implementation details that _need_ to be public should be marked with `#[doc(hidden)]` and a comment as to why it needs to be public.
35-
- Functions which technically need to be public but shouldn't be callable by the user need to be sealed.
33+
- Implementation details that _need_ to be public should be marked with `#[doc(hidden)]` and a comment as to why it needs to be public.
34+
- Functions which technically need to be public but shouldn't be callable by the user need to be sealed.
3635
- see [this example in Rust's core library](https://github.com/rust-lang/rust/blob/044a28a4091f2e1a5883f7fa990223f8b200a2cd/library/core/src/error.rs#L89-L100)
37-
- Any public traits, that **must not** be implemented downstream need to be `Sealed`
36+
- Any public traits, that **must not** be implemented downstream need to be `Sealed`.
3837
- Prefer compile-time checks over runtime checks where possible, prefer a fallible API over panics.
39-
- Follow naming conventions in order to be consistent across drivers - take inspiration from existing drivers
38+
- Follow naming conventions in order to be consistent across drivers - take inspiration from existing drivers.
4039
- Design APIs in a way that they are easy to use.
4140
- Driver API decisions should be assessed individually, don't _not_ just follow embedded-hal or other ecosystem trait crates. Expose the capabilities of the hardware. (Ecosystem traits are implemented on top of the inherent API)
4241
- Avoid type states and extraneous generics whenever possible
@@ -45,6 +44,7 @@ The following paragraphs contain additional recommendations.
4544
- Avoiding `&mut self` when `&self` is safe to use. `&self` is generally easier to use as an API. Typical applications of this are where the methods just do writes to registers which don't have side effects.
4645
- For example starting a timer is fine for `&self`, worst case a timer will be started twice if two parts of the program call it. You can see a real example of this [here](https://github.com/esp-rs/esp-hal/pull/1500#pullrequestreview-2015911974)
4746
- Maintain order consistency in the API, such as in the case of pairs like RX/TX.
47+
- If your driver provides a way to listen for interrupts, the interrupts should be listed in a `derive(EnumSetType)` enum as opposed to one function per interrupt flag.
4848

4949
## Maintainability
5050

esp-hal-embassy/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
99

1010
### Added
1111

12+
- `ESP_HAL_EMBASSY_LOW_POWER_WAIT` configuration option. (#2329)
13+
1214
### Changed
1315

1416
- Reduce memory footprint by 4 bytes on multi-core MCUs.

esp-hal-embassy/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ static_cell = "2.1.0"
2525

2626
[build-dependencies]
2727
esp-build = { version = "0.1.0", path = "../esp-build" }
28+
esp-config = { version = "0.1.0", path = "../esp-config", features = ["build"] }
2829
esp-metadata = { version = "0.4.0", path = "../esp-metadata" }
2930

3031
[features]

esp-hal-embassy/build.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use std::{error::Error, str::FromStr};
22

33
use esp_build::assert_unique_used_features;
4+
use esp_config::{generate_config, Value};
45
use esp_metadata::{Chip, Config};
56

67
fn main() -> Result<(), Box<dyn Error>> {
@@ -37,5 +38,16 @@ fn main() -> Result<(), Box<dyn Error>> {
3738
// Define all necessary configuration symbols for the configured device:
3839
config.define_symbols();
3940

41+
// emit config
42+
generate_config(
43+
"esp_hal_embassy",
44+
&[(
45+
"low-power-wait",
46+
Value::Bool(true),
47+
"Enables the lower-power wait if no tasks are ready to run on the thread-mode executor. This allows the MCU to use less power if the workload allows. Recommended for battery-powered systems. May impact analog performance.",
48+
)],
49+
true,
50+
);
51+
4052
Ok(())
4153
}

esp-hal-embassy/src/executor/thread.rs

Lines changed: 34 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use embassy_executor::{raw, Spawner};
66
use esp_hal::{get_core, Cpu};
77
#[cfg(multi_core)]
88
use esp_hal::{interrupt::software::SoftwareInterrupt, macros::handler};
9+
#[cfg(low_power_wait)]
910
use portable_atomic::{AtomicBool, Ordering};
1011

1112
pub(crate) const THREAD_MODE_CONTEXT: usize = 16;
@@ -15,7 +16,7 @@ pub(crate) const THREAD_MODE_CONTEXT: usize = 16;
1516
static SIGNAL_WORK_THREAD_MODE: [AtomicBool; Cpu::COUNT] =
1617
[const { AtomicBool::new(false) }; Cpu::COUNT];
1718

18-
#[cfg(multi_core)]
19+
#[cfg(all(multi_core, low_power_wait))]
1920
#[handler]
2021
fn software3_interrupt() {
2122
// This interrupt is fired when the thread-mode executor's core needs to be
@@ -25,30 +26,33 @@ fn software3_interrupt() {
2526
unsafe { SoftwareInterrupt::<3>::steal().reset() };
2627
}
2728

28-
pub(crate) fn pend_thread_mode(core: usize) {
29-
// Signal that there is work to be done.
30-
SIGNAL_WORK_THREAD_MODE[core].store(true, Ordering::SeqCst);
31-
32-
// If we are pending a task on the current core, we're done. Otherwise, we
33-
// need to make sure the other core wakes up.
34-
#[cfg(multi_core)]
35-
if core != get_core() as usize {
36-
// We need to clear the interrupt from software. We don't actually
37-
// need it to trigger and run the interrupt handler, we just need to
38-
// kick waiti to return.
39-
unsafe { SoftwareInterrupt::<3>::steal().raise() };
29+
pub(crate) fn pend_thread_mode(_core: usize) {
30+
#[cfg(low_power_wait)]
31+
{
32+
// Signal that there is work to be done.
33+
SIGNAL_WORK_THREAD_MODE[_core].store(true, Ordering::SeqCst);
34+
35+
// If we are pending a task on the current core, we're done. Otherwise, we
36+
// need to make sure the other core wakes up.
37+
#[cfg(multi_core)]
38+
if _core != get_core() as usize {
39+
// We need to clear the interrupt from software. We don't actually
40+
// need it to trigger and run the interrupt handler, we just need to
41+
// kick waiti to return.
42+
unsafe { SoftwareInterrupt::<3>::steal().raise() };
43+
}
4044
}
4145
}
4246

43-
/// A thread aware Executor
47+
/// Thread mode executor.
48+
///
49+
/// This is the simplest and most common kind of executor. It runs on thread
50+
/// mode (at the lowest priority level).
51+
#[cfg_attr(multi_core, doc = "")]
4452
#[cfg_attr(
4553
multi_core,
46-
doc = r#"
47-
This executor is capable of waking an
48-
executor running on another core if work
49-
needs to be completed there for a task to
50-
progress on this core.
51-
"#
54+
doc = "This executor is safe to use on multiple cores. You need to
55+
create one instance per core. The executors don't steal tasks from each other."
5256
)]
5357
pub struct Executor {
5458
inner: raw::Executor,
@@ -64,7 +68,7 @@ impl Executor {
6468
This will use software-interrupt 3 which isn't available for anything else to wake the other core(s)."#
6569
)]
6670
pub fn new() -> Self {
67-
#[cfg(multi_core)]
71+
#[cfg(all(multi_core, low_power_wait))]
6872
unsafe {
6973
SoftwareInterrupt::<3>::steal().set_interrupt_handler(software3_interrupt);
7074
}
@@ -90,28 +94,27 @@ This will use software-interrupt 3 which isn't available for anything else to wa
9094
/// you mutable access. There's a few ways to do this:
9195
///
9296
/// - a [StaticCell](https://docs.rs/static_cell/latest/static_cell/) (safe)
93-
/// - a `static mut` (unsafe)
97+
/// - a `static mut` (unsafe, not recommended)
9498
/// - a local variable in a function you know never returns (like `fn main()
9599
/// -> !`), upgrading its lifetime with `transmute`. (unsafe)
96100
///
97101
/// This function never returns.
98102
pub fn run(&'static mut self, init: impl FnOnce(Spawner)) -> ! {
99103
init(self.inner.spawner());
100104

105+
#[cfg(low_power_wait)]
101106
let cpu = get_core() as usize;
102107

103108
loop {
104-
unsafe {
105-
self.inner.poll();
109+
unsafe { self.inner.poll() };
106110

107-
Self::wait_impl(cpu);
108-
}
111+
#[cfg(low_power_wait)]
112+
Self::wait_impl(cpu);
109113
}
110114
}
111115

112-
#[doc(hidden)]
113-
#[cfg(xtensa)]
114-
pub fn wait_impl(cpu: usize) {
116+
#[cfg(all(xtensa, low_power_wait))]
117+
fn wait_impl(cpu: usize) {
115118
// Manual critical section implementation that only masks interrupts handlers.
116119
// We must not acquire the cross-core on dual-core systems because that would
117120
// prevent the other core from doing useful work while this core is sleeping.
@@ -140,9 +143,8 @@ This will use software-interrupt 3 which isn't available for anything else to wa
140143
}
141144
}
142145

143-
#[doc(hidden)]
144-
#[cfg(riscv)]
145-
pub fn wait_impl(cpu: usize) {
146+
#[cfg(all(riscv, low_power_wait))]
147+
fn wait_impl(cpu: usize) {
146148
// we do not care about race conditions between the load and store operations,
147149
// interrupts will only set this value to true.
148150
critical_section::with(|_| {

esp-hal/CHANGELOG.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
88
## [Unreleased]
99

1010
### Added
11-
1211
- A new config option `PLACE_SWITCH_TABLES_IN_RAM` to improve performance (especially for interrupts) at the cost of slightly more RAM usage (#2331)
1312
- A new config option `PLACE_ANON_IN_RAM` to improve performance (especially for interrupts) at the cost of RAM usage (#2331)
1413
- Add burst transfer support to DMA buffers (#2336)
@@ -23,6 +22,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
2322
- `Cpu::COUNT` and `Cpu::current()` (#?)
2423
- Add RGB/DPI driver (#2415)
2524
- Add `DmaLoopBuf` (#2415)
25+
- `Cpu::COUNT` and `Cpu::current()` (#2411)
26+
- `UartInterrupt` and related functions (#2406)
27+
- I2S Parallel output driver for esp32. (#2348)
28+
- Add an option to configure `WDT` action (#2330)
2629

2730
### Changed
2831

@@ -33,11 +36,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
3336
- The SPI driver has been rewritten to allow using half-duplex and full-duplex functionality on the same bus. See the migration guide for details. (#2373)
3437
- Renamed `SpiDma` functions: `dma_transfer` to `transfer`, `dma_write` to `write`, `dma_read` to `read`. (#2373)
3538
- Peripheral type erasure for UART (#2381)
39+
- Changed listening for UART events (#2406)
40+
- Circular DMA transfers now correctly error, `available` returns `Result<usize,DmaError>` now (#2409)
3641

3742
### Fixed
3843

3944
- Fix conflict between `RtcClock::get_xtal_freq` and `Rtc::disable_rom_message_printing` (#2360)
4045
- Fixed an issue where interrupts enabled before `esp_hal::init` were disabled. This issue caused the executor created by `#[esp_hal_embassy::main]` to behave incorrectly in multi-core applications. (#2377)
46+
- Fixed `TWAI::transmit_async`: bus-off state is not reached when CANH and CANL are shorted. (#2421)
4147

4248
### Removed
4349

esp-hal/MIGRATING-0.21.md

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,3 +118,61 @@ The `Spi<'_, SPI, HalfDuplexMode>::read` and `Spi<'_, SPI, HalfDuplexMode>::writ
118118
)
119119
.unwrap();
120120
```
121+
122+
## UART event listening
123+
124+
The following functions have been removed:
125+
126+
- `listen_at_cmd`
127+
- `unlisten_at_cmd`
128+
- `listen_tx_done`
129+
- `unlisten_tx_done`
130+
- `listen_rx_fifo_full`
131+
- `unlisten_rx_fifo_full`
132+
- `at_cmd_interrupt_set`
133+
- `tx_done_interrupt_set`
134+
- `rx_fifo_full_interrupt_set`
135+
- `reset_at_cmd_interrupt`
136+
- `reset_tx_done_interrupt`
137+
- `reset_rx_fifo_full_interrupt`
138+
139+
You can now use the `UartInterrupt` enum and the corresponding `listen`, `unlisten`, `interrupts` and `clear_interrupts` functions.
140+
141+
Use `interrupts` in place of `<INTERRUPT>_interrupt_set` and `clear_interrupts` in place of the old `reset_` functions.
142+
143+
`UartInterrupt`:
144+
- `AtCmd`
145+
- `TxDone`
146+
- `RxFifoFull`
147+
148+
Checking interrupt bits is now done using APIs provided by [enumset](https://docs.rs/enumset/1.1.5/enumset/index.html). For example, to see if
149+
a particular interrupt bit is set, use `contains`:
150+
151+
```diff
152+
-serial.at_cmd_interrupt_set()
153+
+serial.interupts().contains(UartInterrupt::AtCmd)
154+
```
155+
156+
You can now listen/unlisten multiple interrupt bits at once:
157+
158+
```diff
159+
-uart0.listen_at_cmd();
160+
-uart0.listen_rx_fifo_full();
161+
+uart0.listen(UartInterrupt::AtCmd | UartConterrupt::RxFifoFull);
162+
```˛
163+
## Circular DMA transfer's `available` returns `Result<usize, DmaError>` now
164+
165+
In case of any error you should drop the transfer and restart it.
166+
167+
```diff
168+
loop {
169+
- let avail = transfer.available();
170+
+ let avail = match transfer.available() {
171+
+ Ok(avail) => avail,
172+
+ Err(_) => {
173+
+ core::mem::drop(transfer);
174+
+ transfer = i2s_tx.write_dma_circular(&tx_buffer).unwrap();
175+
+ continue;
176+
+ },
177+
+ };
178+
```

esp-hal/src/dma/gdma.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,12 @@ impl<C: GdmaChannel> RegisterAccess for ChannelTxImpl<C> {
151151
}
152152

153153
impl<C: GdmaChannel> TxRegisterAccess for ChannelTxImpl<C> {
154+
fn set_auto_write_back(&self, enable: bool) {
155+
self.ch()
156+
.out_conf0()
157+
.modify(|_, w| w.out_auto_wrback().bit(enable));
158+
}
159+
154160
fn last_dscr_address(&self) -> usize {
155161
self.ch()
156162
.out_eof_des_addr()

0 commit comments

Comments
 (0)