aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-x.github/ci/build.sh2
-rwxr-xr-x.github/ci/test-nightly.sh1
-rwxr-xr-x.github/ci/test.sh7
-rw-r--r--NOTICE.md2
-rw-r--r--README.md8
-rwxr-xr-xci.sh3
-rw-r--r--embassy-boot-nrf/README.md2
-rw-r--r--embassy-boot/README.md2
-rw-r--r--embassy-futures/src/yield_now.rs8
-rw-r--r--embassy-net/Cargo.toml6
-rw-r--r--embassy-net/README.md4
-rw-r--r--embassy-net/src/lib.rs2
-rw-r--r--embassy-net/src/raw.rs120
-rw-r--r--embassy-nrf/CHANGELOG.md40
-rw-r--r--embassy-stm32/Cargo.toml38
-rw-r--r--embassy-stm32/build.rs3
-rw-r--r--embassy-stm32/src/adc/f1.rs12
-rw-r--r--embassy-stm32/src/adc/f3.rs11
-rw-r--r--embassy-stm32/src/adc/g4.rs304
-rw-r--r--embassy-stm32/src/adc/mod.rs38
-rw-r--r--embassy-stm32/src/adc/v1.rs15
-rw-r--r--embassy-stm32/src/adc/v2.rs9
-rw-r--r--embassy-stm32/src/adc/v3.rs30
-rw-r--r--embassy-stm32/src/adc/v4.rs13
-rw-r--r--embassy-stm32/src/crc/v1.rs12
-rw-r--r--embassy-stm32/src/crc/v2v3.rs16
-rw-r--r--embassy-stm32/src/exti.rs16
-rw-r--r--embassy-stm32/src/flash/f4.rs5
-rw-r--r--embassy-stm32/src/flash/h50.rs6
-rw-r--r--embassy-stm32/src/flash/mod.rs2
-rw-r--r--embassy-stm32/src/rcc/l.rs28
-rw-r--r--embassy-stm32/src/rcc/mco.rs2
-rw-r--r--embassy-stm32/src/rcc/mod.rs22
-rw-r--r--embassy-stm32/src/spi/mod.rs17
-rw-r--r--embassy-stm32/src/usb/otg.rs62
-rw-r--r--embassy-sync/CHANGELOG.md5
-rw-r--r--embassy-sync/src/channel.rs27
-rw-r--r--embassy-sync/src/mutex.rs133
-rw-r--r--embassy-time-queue-driver/README.md2
-rw-r--r--embassy-time/README.md2
-rw-r--r--embassy-usb/README.md4
-rw-r--r--embassy-usb/src/builder.rs9
-rw-r--r--examples/boot/bootloader/stm32-dual-bank/README.md8
-rw-r--r--examples/rp/Cargo.toml2
-rw-r--r--examples/stm32f0/src/bin/adc.rs6
-rw-r--r--examples/stm32f0/src/bin/multiprio.rs5
-rw-r--r--examples/stm32f1/src/bin/adc.rs6
-rw-r--r--examples/stm32f3/src/bin/multiprio.rs5
-rw-r--r--examples/stm32f334/src/bin/adc.rs6
-rw-r--r--examples/stm32f334/src/bin/opamp.rs6
-rw-r--r--examples/stm32f4/src/bin/adc.rs2
-rw-r--r--examples/stm32f4/src/bin/multiprio.rs5
-rw-r--r--examples/stm32f4/src/bin/usb_hid_keyboard.rs1
-rw-r--r--examples/stm32f4/src/bin/ws2812_spi.rs2
-rw-r--r--examples/stm32f7/src/bin/adc.rs4
-rw-r--r--examples/stm32g4/src/bin/adc.rs6
-rw-r--r--examples/stm32h7/src/bin/adc.rs4
-rw-r--r--examples/stm32h7/src/bin/multiprio.rs5
-rw-r--r--examples/stm32l0/src/bin/adc.rs6
-rw-r--r--examples/stm32l4/src/bin/adc.rs3
-rw-r--r--examples/stm32u0/.cargo/config.toml9
-rw-r--r--examples/stm32u0/Cargo.toml25
-rw-r--r--examples/stm32u0/build.rs5
-rw-r--r--examples/stm32u0/src/bin/blinky.rs26
-rw-r--r--examples/stm32u0/src/bin/button.rs24
-rw-r--r--examples/stm32u0/src/bin/button_exti.rs25
-rw-r--r--rust-toolchain-nightly.toml2
-rw-r--r--tests/stm32/src/bin/dac.rs4
68 files changed, 1065 insertions, 187 deletions
diff --git a/.github/ci/build.sh b/.github/ci/build.sh
index 77d2b3cab..68a7c0c34 100755
--- a/.github/ci/build.sh
+++ b/.github/ci/build.sh
@@ -7,7 +7,7 @@ set -euo pipefail
7export RUSTUP_HOME=/ci/cache/rustup 7export RUSTUP_HOME=/ci/cache/rustup
8export CARGO_HOME=/ci/cache/cargo 8export CARGO_HOME=/ci/cache/cargo
9export CARGO_TARGET_DIR=/ci/cache/target 9export CARGO_TARGET_DIR=/ci/cache/target
10if [ -f /ci/secrets/teleprobe-token.txt ]; then 10if [ -f /ci/secrets/teleprobe-token.txt ]; then
11 echo Got teleprobe token! 11 echo Got teleprobe token!
12 export TELEPROBE_HOST=https://teleprobe.embassy.dev 12 export TELEPROBE_HOST=https://teleprobe.embassy.dev
13 export TELEPROBE_TOKEN=$(cat /ci/secrets/teleprobe-token.txt) 13 export TELEPROBE_TOKEN=$(cat /ci/secrets/teleprobe-token.txt)
diff --git a/.github/ci/test-nightly.sh b/.github/ci/test-nightly.sh
index d6e5dc574..1724ffe89 100755
--- a/.github/ci/test-nightly.sh
+++ b/.github/ci/test-nightly.sh
@@ -11,3 +11,4 @@ mv rust-toolchain-nightly.toml rust-toolchain.toml
11 11
12MIRIFLAGS=-Zmiri-ignore-leaks cargo miri test --manifest-path ./embassy-executor/Cargo.toml 12MIRIFLAGS=-Zmiri-ignore-leaks cargo miri test --manifest-path ./embassy-executor/Cargo.toml
13MIRIFLAGS=-Zmiri-ignore-leaks cargo miri test --manifest-path ./embassy-executor/Cargo.toml --features nightly 13MIRIFLAGS=-Zmiri-ignore-leaks cargo miri test --manifest-path ./embassy-executor/Cargo.toml --features nightly
14MIRIFLAGS=-Zmiri-ignore-leaks cargo miri test --manifest-path ./embassy-sync/Cargo.toml
diff --git a/.github/ci/test.sh b/.github/ci/test.sh
index 8a58939f6..41da644fc 100755
--- a/.github/ci/test.sh
+++ b/.github/ci/test.sh
@@ -8,9 +8,10 @@ export RUSTUP_HOME=/ci/cache/rustup
8export CARGO_HOME=/ci/cache/cargo 8export CARGO_HOME=/ci/cache/cargo
9export CARGO_TARGET_DIR=/ci/cache/target 9export CARGO_TARGET_DIR=/ci/cache/target
10 10
11cargo test --manifest-path ./embassy-sync/Cargo.toml 11cargo test --manifest-path ./embassy-futures/Cargo.toml
12cargo test --manifest-path ./embassy-embedded-hal/Cargo.toml 12cargo test --manifest-path ./embassy-sync/Cargo.toml
13cargo test --manifest-path ./embassy-hal-internal/Cargo.toml 13cargo test --manifest-path ./embassy-embedded-hal/Cargo.toml
14cargo test --manifest-path ./embassy-hal-internal/Cargo.toml
14cargo test --manifest-path ./embassy-time/Cargo.toml --features generic-queue,mock-driver 15cargo test --manifest-path ./embassy-time/Cargo.toml --features generic-queue,mock-driver
15cargo test --manifest-path ./embassy-time-driver/Cargo.toml 16cargo test --manifest-path ./embassy-time-driver/Cargo.toml
16 17
diff --git a/NOTICE.md b/NOTICE.md
index 868bec08f..a50b39494 100644
--- a/NOTICE.md
+++ b/NOTICE.md
@@ -12,5 +12,5 @@ listed source code repository logs.
12 12
13This program and the accompanying materials are made available under the terms 13This program and the accompanying materials are made available under the terms
14of the Apache Software License 2.0 which is available at 14of the Apache Software License 2.0 which is available at
15https://www.apache.org/licenses/LICENSE-2.0, or the MIT license which is 15https://www.apache.org/licenses/LICENSE-2.0, or the MIT license which is
16available at https://opensource.org/licenses/MIT 16available at https://opensource.org/licenses/MIT
diff --git a/README.md b/README.md
index b6f667f75..0bd1ac594 100644
--- a/README.md
+++ b/README.md
@@ -7,7 +7,7 @@ Embassy is the next-generation framework for embedded applications. Write safe,
7 7
8The Rust programming language is blazingly fast and memory-efficient, with no runtime, garbage collector or OS. It catches a wide variety of bugs at compile time, thanks to its full memory- and thread-safety, and expressive type system. 8The Rust programming language is blazingly fast and memory-efficient, with no runtime, garbage collector or OS. It catches a wide variety of bugs at compile time, thanks to its full memory- and thread-safety, and expressive type system.
9 9
10Rust's <a href="https://rust-lang.github.io/async-book/">async/await</a> allows for unprecedently easy and efficient multitasking in embedded systems. Tasks get transformed at compile time into state machines that get run cooperatively. It requires no dynamic memory allocation, and runs on a single stack, so no per-task stack size tuning is required. It obsoletes the need for a traditional RTOS with kernel context switching, and is <a href="https://tweedegolf.nl/en/blog/65/async-rust-vs-rtos-showdown">faster and smaller than one!</a> 10Rust's <a href="https://rust-lang.github.io/async-book/">async/await</a> allows for unprecedentedly easy and efficient multitasking in embedded systems. Tasks get transformed at compile time into state machines that get run cooperatively. It requires no dynamic memory allocation, and runs on a single stack, so no per-task stack size tuning is required. It obsoletes the need for a traditional RTOS with kernel context switching, and is <a href="https://tweedegolf.nl/en/blog/65/async-rust-vs-rtos-showdown">faster and smaller than one!</a>
11 11
12## Batteries included 12## Batteries included
13 13
@@ -89,7 +89,7 @@ async fn main(spawner: Spawner) {
89 89
90## Examples 90## Examples
91 91
92Examples are found in the `examples/` folder seperated by the chip manufacturer they are designed to run on. For example: 92Examples are found in the `examples/` folder separated by the chip manufacturer they are designed to run on. For example:
93 93
94* `examples/nrf52840` run on the `nrf52840-dk` board (PCA10056) but should be easily adaptable to other nRF52 chips and boards. 94* `examples/nrf52840` run on the `nrf52840-dk` board (PCA10056) but should be easily adaptable to other nRF52 chips and boards.
95* `examples/nrf5340` run on the `nrf5340-dk` board (PCA10095). 95* `examples/nrf5340` run on the `nrf5340-dk` board (PCA10095).
@@ -130,8 +130,8 @@ For more help getting started, see [Getting Started][1] and [Running the Example
130## Developing Embassy with Rust Analyzer based editors 130## Developing Embassy with Rust Analyzer based editors
131 131
132The [Rust Analyzer](https://rust-analyzer.github.io/) is used by [Visual Studio Code](https://code.visualstudio.com/) 132The [Rust Analyzer](https://rust-analyzer.github.io/) is used by [Visual Studio Code](https://code.visualstudio.com/)
133and others. Given the multiple targets that Embassy serves, there is no Cargo workspace file. Instead, the Rust Analyzer 133and others. Given the multiple targets that Embassy serves, there is no Cargo workspace file. Instead, the Rust Analyzer
134must be told of the target project to work with. In the case of Visual Studio Code, 134must be told of the target project to work with. In the case of Visual Studio Code,
135please refer to the `.vscode/settings.json` file's `rust-analyzer.linkedProjects`setting. 135please refer to the `.vscode/settings.json` file's `rust-analyzer.linkedProjects`setting.
136 136
137## Minimum supported Rust version (MSRV) 137## Minimum supported Rust version (MSRV)
diff --git a/ci.sh b/ci.sh
index d17f4e13e..1393b9d47 100755
--- a/ci.sh
+++ b/ci.sh
@@ -149,6 +149,9 @@ cargo batch \
149 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32h503rb,defmt,exti,time-driver-any,time \ 149 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32h503rb,defmt,exti,time-driver-any,time \
150 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32h562ag,defmt,exti,time-driver-any,time \ 150 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32h562ag,defmt,exti,time-driver-any,time \
151 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32wb35ce,defmt,exti,time-driver-any,time \ 151 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32wb35ce,defmt,exti,time-driver-any,time \
152 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32u031r8,defmt,exti,time-driver-any,time \
153 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32u073mb,defmt,exti,time-driver-any,time \
154 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32u083rc,defmt,exti,time-driver-any,time \
152 --- build --release --manifest-path cyw43/Cargo.toml --target thumbv6m-none-eabi --features ''\ 155 --- build --release --manifest-path cyw43/Cargo.toml --target thumbv6m-none-eabi --features ''\
153 --- build --release --manifest-path cyw43/Cargo.toml --target thumbv6m-none-eabi --features 'log' \ 156 --- build --release --manifest-path cyw43/Cargo.toml --target thumbv6m-none-eabi --features 'log' \
154 --- build --release --manifest-path cyw43/Cargo.toml --target thumbv6m-none-eabi --features 'defmt' \ 157 --- build --release --manifest-path cyw43/Cargo.toml --target thumbv6m-none-eabi --features 'defmt' \
diff --git a/embassy-boot-nrf/README.md b/embassy-boot-nrf/README.md
index 9dc5b0eb9..f0d87e18c 100644
--- a/embassy-boot-nrf/README.md
+++ b/embassy-boot-nrf/README.md
@@ -2,7 +2,7 @@
2 2
3An [Embassy](https://embassy.dev) project. 3An [Embassy](https://embassy.dev) project.
4 4
5An adaptation of `embassy-boot` for nRF. 5An adaptation of `embassy-boot` for nRF.
6 6
7## Features 7## Features
8 8
diff --git a/embassy-boot/README.md b/embassy-boot/README.md
index 3c2d45e96..812c43524 100644
--- a/embassy-boot/README.md
+++ b/embassy-boot/README.md
@@ -15,7 +15,7 @@ The bootloader divides the storage into 4 main partitions, configurable when cre
15* BOOTLOADER - Where the bootloader is placed. The bootloader itself consumes about 8kB of flash, but if you need to debug it and have space available, increasing this to 24kB will allow you to run the bootloader with probe-rs. 15* BOOTLOADER - Where the bootloader is placed. The bootloader itself consumes about 8kB of flash, but if you need to debug it and have space available, increasing this to 24kB will allow you to run the bootloader with probe-rs.
16* ACTIVE - Where the main application is placed. The bootloader will attempt to load the application at the start of this partition. The minimum size required for this partition is the size of your application. 16* ACTIVE - Where the main application is placed. The bootloader will attempt to load the application at the start of this partition. The minimum size required for this partition is the size of your application.
17* DFU - Where the application-to-be-swapped is placed. This partition is written to by the application. This partition must be at least 1 page bigger than the ACTIVE partition. 17* DFU - Where the application-to-be-swapped is placed. This partition is written to by the application. This partition must be at least 1 page bigger than the ACTIVE partition.
18* BOOTLOADER STATE - Where the bootloader stores the current state describing if the active and dfu partitions need to be swapped. 18* BOOTLOADER STATE - Where the bootloader stores the current state describing if the active and dfu partitions need to be swapped.
19 19
20For any partition, the following preconditions are required: 20For any partition, the following preconditions are required:
21 21
diff --git a/embassy-futures/src/yield_now.rs b/embassy-futures/src/yield_now.rs
index bb3c67d17..4d4e535f2 100644
--- a/embassy-futures/src/yield_now.rs
+++ b/embassy-futures/src/yield_now.rs
@@ -9,10 +9,16 @@ use core::task::{Context, Poll};
9/// hold, while still allowing other tasks to run concurrently (not monopolizing 9/// hold, while still allowing other tasks to run concurrently (not monopolizing
10/// the executor thread). 10/// the executor thread).
11/// 11///
12/// ```rust,no_run 12/// ```rust
13/// # use embassy_futures::{block_on, yield_now};
14/// # async fn test_fn() {
15/// # let mut iter_count: u32 = 0;
16/// # let mut some_condition = || { iter_count += 1; iter_count > 10 };
13/// while !some_condition() { 17/// while !some_condition() {
14/// yield_now().await; 18/// yield_now().await;
15/// } 19/// }
20/// # }
21/// # block_on(test_fn());
16/// ``` 22/// ```
17/// 23///
18/// The downside is this will spin in a busy loop, using 100% of the CPU, while 24/// The downside is this will spin in a busy loop, using 100% of the CPU, while
diff --git a/embassy-net/Cargo.toml b/embassy-net/Cargo.toml
index be9f1d784..ee7289ad8 100644
--- a/embassy-net/Cargo.toml
+++ b/embassy-net/Cargo.toml
@@ -16,11 +16,11 @@ categories = [
16[package.metadata.embassy_docs] 16[package.metadata.embassy_docs]
17src_base = "https://github.com/embassy-rs/embassy/blob/embassy-net-v$VERSION/embassy-net/src/" 17src_base = "https://github.com/embassy-rs/embassy/blob/embassy-net-v$VERSION/embassy-net/src/"
18src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-net/src/" 18src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-net/src/"
19features = ["defmt", "tcp", "udp", "dns", "dhcpv4", "proto-ipv6", "medium-ethernet", "medium-ip", "medium-ieee802154", "igmp", "dhcpv4-hostname"] 19features = ["defmt", "tcp", "udp", "raw", "dns", "dhcpv4", "proto-ipv6", "medium-ethernet", "medium-ip", "medium-ieee802154", "igmp", "dhcpv4-hostname"]
20target = "thumbv7em-none-eabi" 20target = "thumbv7em-none-eabi"
21 21
22[package.metadata.docs.rs] 22[package.metadata.docs.rs]
23features = ["defmt", "tcp", "udp", "dns", "dhcpv4", "proto-ipv6", "medium-ethernet", "medium-ip", "medium-ieee802154", "igmp", "dhcpv4-hostname"] 23features = ["defmt", "tcp", "udp", "raw", "dns", "dhcpv4", "proto-ipv6", "medium-ethernet", "medium-ip", "medium-ieee802154", "igmp", "dhcpv4-hostname"]
24 24
25[features] 25[features]
26default = [] 26default = []
@@ -38,6 +38,8 @@ packet-trace = []
38 38
39## Enable UDP support 39## Enable UDP support
40udp = ["smoltcp/socket-udp"] 40udp = ["smoltcp/socket-udp"]
41## Enable Raw support
42raw = ["smoltcp/socket-raw"]
41## Enable TCP support 43## Enable TCP support
42tcp = ["smoltcp/socket-tcp"] 44tcp = ["smoltcp/socket-tcp"]
43## Enable DNS support 45## Enable DNS support
diff --git a/embassy-net/README.md b/embassy-net/README.md
index 94aa6f550..ce59ea34a 100644
--- a/embassy-net/README.md
+++ b/embassy-net/README.md
@@ -13,8 +13,8 @@ memory management designed to work well for embedded systems, aiming for a more
13- TCP, UDP, DNS, DHCPv4, IGMPv4 13- TCP, UDP, DNS, DHCPv4, IGMPv4
14- TCP sockets implement the `embedded-io` async traits. 14- TCP sockets implement the `embedded-io` async traits.
15 15
16See the [`smoltcp`](https://github.com/smoltcp-rs/smoltcp) README for a detailed list of implemented and 16See the [`smoltcp`](https://github.com/smoltcp-rs/smoltcp) README for a detailed list of implemented and
17unimplemented features of the network protocols. 17unimplemented features of the network protocols.
18 18
19## Hardware support 19## Hardware support
20 20
diff --git a/embassy-net/src/lib.rs b/embassy-net/src/lib.rs
index 1c0cf1a12..86ced1ded 100644
--- a/embassy-net/src/lib.rs
+++ b/embassy-net/src/lib.rs
@@ -15,6 +15,8 @@ pub(crate) mod fmt;
15mod device; 15mod device;
16#[cfg(feature = "dns")] 16#[cfg(feature = "dns")]
17pub mod dns; 17pub mod dns;
18#[cfg(feature = "raw")]
19pub mod raw;
18#[cfg(feature = "tcp")] 20#[cfg(feature = "tcp")]
19pub mod tcp; 21pub mod tcp;
20mod time; 22mod time;
diff --git a/embassy-net/src/raw.rs b/embassy-net/src/raw.rs
new file mode 100644
index 000000000..7ecd913e7
--- /dev/null
+++ b/embassy-net/src/raw.rs
@@ -0,0 +1,120 @@
1//! Raw sockets.
2
3use core::cell::RefCell;
4use core::future::poll_fn;
5use core::mem;
6use core::task::{Context, Poll};
7
8use embassy_net_driver::Driver;
9use smoltcp::iface::{Interface, SocketHandle};
10use smoltcp::socket::raw;
11pub use smoltcp::socket::raw::PacketMetadata;
12use smoltcp::wire::{IpProtocol, IpVersion};
13
14use crate::{SocketStack, Stack};
15
16/// Error returned by [`RawSocket::recv`] and [`RawSocket::send`].
17#[derive(PartialEq, Eq, Clone, Copy, Debug)]
18#[cfg_attr(feature = "defmt", derive(defmt::Format))]
19pub enum RecvError {
20 /// Provided buffer was smaller than the received packet.
21 Truncated,
22}
23
24/// An Raw socket.
25pub struct RawSocket<'a> {
26 stack: &'a RefCell<SocketStack>,
27 handle: SocketHandle,
28}
29
30impl<'a> RawSocket<'a> {
31 /// Create a new Raw socket using the provided stack and buffers.
32 pub fn new<D: Driver>(
33 stack: &'a Stack<D>,
34 ip_version: IpVersion,
35 ip_protocol: IpProtocol,
36 rx_meta: &'a mut [PacketMetadata],
37 rx_buffer: &'a mut [u8],
38 tx_meta: &'a mut [PacketMetadata],
39 tx_buffer: &'a mut [u8],
40 ) -> Self {
41 let s = &mut *stack.socket.borrow_mut();
42
43 let rx_meta: &'static mut [PacketMetadata] = unsafe { mem::transmute(rx_meta) };
44 let rx_buffer: &'static mut [u8] = unsafe { mem::transmute(rx_buffer) };
45 let tx_meta: &'static mut [PacketMetadata] = unsafe { mem::transmute(tx_meta) };
46 let tx_buffer: &'static mut [u8] = unsafe { mem::transmute(tx_buffer) };
47 let handle = s.sockets.add(raw::Socket::new(
48 ip_version,
49 ip_protocol,
50 raw::PacketBuffer::new(rx_meta, rx_buffer),
51 raw::PacketBuffer::new(tx_meta, tx_buffer),
52 ));
53
54 Self {
55 stack: &stack.socket,
56 handle,
57 }
58 }
59
60 fn with_mut<R>(&self, f: impl FnOnce(&mut raw::Socket, &mut Interface) -> R) -> R {
61 let s = &mut *self.stack.borrow_mut();
62 let socket = s.sockets.get_mut::<raw::Socket>(self.handle);
63 let res = f(socket, &mut s.iface);
64 s.waker.wake();
65 res
66 }
67
68 /// Receive a datagram.
69 ///
70 /// This method will wait until a datagram is received.
71 pub async fn recv(&self, buf: &mut [u8]) -> Result<usize, RecvError> {
72 poll_fn(move |cx| self.poll_recv(buf, cx)).await
73 }
74
75 /// Receive a datagram.
76 ///
77 /// When no datagram is available, this method will return `Poll::Pending` and
78 /// register the current task to be notified when a datagram is received.
79 pub fn poll_recv(&self, buf: &mut [u8], cx: &mut Context<'_>) -> Poll<Result<usize, RecvError>> {
80 self.with_mut(|s, _| match s.recv_slice(buf) {
81 Ok(n) => Poll::Ready(Ok(n)),
82 // No data ready
83 Err(raw::RecvError::Truncated) => Poll::Ready(Err(RecvError::Truncated)),
84 Err(raw::RecvError::Exhausted) => {
85 s.register_recv_waker(cx.waker());
86 Poll::Pending
87 }
88 })
89 }
90
91 /// Send a datagram.
92 ///
93 /// This method will wait until the datagram has been sent.`
94 pub async fn send(&self, buf: &[u8]) {
95 poll_fn(move |cx| self.poll_send(buf, cx)).await
96 }
97
98 /// Send a datagram.
99 ///
100 /// When the datagram has been sent, this method will return `Poll::Ready(Ok())`.
101 ///
102 /// When the socket's send buffer is full, this method will return `Poll::Pending`
103 /// and register the current task to be notified when the buffer has space available.
104 pub fn poll_send(&self, buf: &[u8], cx: &mut Context<'_>) -> Poll<()> {
105 self.with_mut(|s, _| match s.send_slice(buf) {
106 // Entire datagram has been sent
107 Ok(()) => Poll::Ready(()),
108 Err(raw::SendError::BufferFull) => {
109 s.register_send_waker(cx.waker());
110 Poll::Pending
111 }
112 })
113 }
114}
115
116impl Drop for RawSocket<'_> {
117 fn drop(&mut self) {
118 self.stack.borrow_mut().sockets.remove(self.handle);
119 }
120}
diff --git a/embassy-nrf/CHANGELOG.md b/embassy-nrf/CHANGELOG.md
new file mode 100644
index 000000000..773a1a108
--- /dev/null
+++ b/embassy-nrf/CHANGELOG.md
@@ -0,0 +1,40 @@
1# Changelog for embassy-nrf
2
3All notable changes to this project will be documented in this file.
4
5The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
8## Unreleased
9
10- Drop `sealed` mod
11- nrf52840: Add dcdc voltage parameter to configure REG0 regulator
12- radio: Add support for IEEE 802.15.4 and BLE via radio peripheral
13- spim: Reduce trace-level messages ("Copying SPIM tx buffer..")
14- uart: Add support for rx- or tx-only BufferedUart
15- uart: Implement splitting Rx/Tx
16- spi: Allow specifying OutputDrive for SPI spins
17- pdm: Fix gain register value derivation
18- spim: Implement chunked DMA transfers
19- spi: Add bounds checks for EasyDMA buffer size
20- uarte: Add support for handling RX errors
21- nrf51: Implement support for nrf51 chip
22- pwm: Expose `duty` method
23- pwm: Fix infinite loop
24- spi: Add support for configuring bit order for bus
25- pwm: Expose `pwm::PWM_CLK_HZ` and add `is_enabled` method
26- gpio: Drop GPIO Pin generics (API break)
27
28## 0.1.0 - 2024-01-12
29
30- First release with support for following NRF chips:
31 - nrf52805
32 - nrf52810
33 - nrf52811
34 - nrf52820
35 - nrf52832
36 - nrf52833
37 - nrf52840
38 - nrf5340
39 - nrf9160
40
diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml
index 89b24f0eb..459d2e370 100644
--- a/embassy-stm32/Cargo.toml
+++ b/embassy-stm32/Cargo.toml
@@ -30,6 +30,7 @@ flavors = [
30 { regex_feature = "stm32l1.*", target = "thumbv7m-none-eabi" }, 30 { regex_feature = "stm32l1.*", target = "thumbv7m-none-eabi" },
31 { regex_feature = "stm32l4.*", target = "thumbv7em-none-eabi" }, 31 { regex_feature = "stm32l4.*", target = "thumbv7em-none-eabi" },
32 { regex_feature = "stm32l5.*", target = "thumbv8m.main-none-eabihf", features = ["low-power"] }, 32 { regex_feature = "stm32l5.*", target = "thumbv8m.main-none-eabihf", features = ["low-power"] },
33 { regex_feature = "stm32u0.*", target = "thumbv6m-none-eabi" },
33 { regex_feature = "stm32u5.*", target = "thumbv8m.main-none-eabihf" }, 34 { regex_feature = "stm32u5.*", target = "thumbv8m.main-none-eabihf" },
34 { regex_feature = "stm32wb.*", target = "thumbv7em-none-eabi" }, 35 { regex_feature = "stm32wb.*", target = "thumbv7em-none-eabi" },
35 { regex_feature = "stm32wba.*", target = "thumbv8m.main-none-eabihf" }, 36 { regex_feature = "stm32wba.*", target = "thumbv8m.main-none-eabihf" },
@@ -70,7 +71,7 @@ rand_core = "0.6.3"
70sdio-host = "0.5.0" 71sdio-host = "0.5.0"
71critical-section = "1.1" 72critical-section = "1.1"
72#stm32-metapac = { version = "15" } 73#stm32-metapac = { version = "15" }
73stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-2b7ec569a5510c324693f0515ac8ea20b12917a9" } 74stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-d674277b78ca7400ecfeeb1b5af4e460a65c1a61" }
74 75
75vcell = "0.1.3" 76vcell = "0.1.3"
76nb = "1.0.0" 77nb = "1.0.0"
@@ -96,7 +97,7 @@ proc-macro2 = "1.0.36"
96quote = "1.0.15" 97quote = "1.0.15"
97 98
98#stm32-metapac = { version = "15", default-features = false, features = ["metadata"]} 99#stm32-metapac = { version = "15", default-features = false, features = ["metadata"]}
99stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-2b7ec569a5510c324693f0515ac8ea20b12917a9", default-features = false, features = ["metadata"]} 100stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-d674277b78ca7400ecfeeb1b5af4e460a65c1a61", default-features = false, features = ["metadata"]}
100 101
101[features] 102[features]
102default = ["rt"] 103default = ["rt"]
@@ -1419,6 +1420,38 @@ stm32l562qe = [ "stm32-metapac/stm32l562qe" ]
1419stm32l562re = [ "stm32-metapac/stm32l562re" ] 1420stm32l562re = [ "stm32-metapac/stm32l562re" ]
1420stm32l562ve = [ "stm32-metapac/stm32l562ve" ] 1421stm32l562ve = [ "stm32-metapac/stm32l562ve" ]
1421stm32l562ze = [ "stm32-metapac/stm32l562ze" ] 1422stm32l562ze = [ "stm32-metapac/stm32l562ze" ]
1423stm32u031c6 = [ "stm32-metapac/stm32u031c6" ]
1424stm32u031c8 = [ "stm32-metapac/stm32u031c8" ]
1425stm32u031f4 = [ "stm32-metapac/stm32u031f4" ]
1426stm32u031f6 = [ "stm32-metapac/stm32u031f6" ]
1427stm32u031f8 = [ "stm32-metapac/stm32u031f8" ]
1428stm32u031g6 = [ "stm32-metapac/stm32u031g6" ]
1429stm32u031g8 = [ "stm32-metapac/stm32u031g8" ]
1430stm32u031k4 = [ "stm32-metapac/stm32u031k4" ]
1431stm32u031k6 = [ "stm32-metapac/stm32u031k6" ]
1432stm32u031k8 = [ "stm32-metapac/stm32u031k8" ]
1433stm32u031r6 = [ "stm32-metapac/stm32u031r6" ]
1434stm32u031r8 = [ "stm32-metapac/stm32u031r8" ]
1435stm32u073c8 = [ "stm32-metapac/stm32u073c8" ]
1436stm32u073cb = [ "stm32-metapac/stm32u073cb" ]
1437stm32u073cc = [ "stm32-metapac/stm32u073cc" ]
1438stm32u073h8 = [ "stm32-metapac/stm32u073h8" ]
1439stm32u073hb = [ "stm32-metapac/stm32u073hb" ]
1440stm32u073hc = [ "stm32-metapac/stm32u073hc" ]
1441stm32u073k8 = [ "stm32-metapac/stm32u073k8" ]
1442stm32u073kb = [ "stm32-metapac/stm32u073kb" ]
1443stm32u073kc = [ "stm32-metapac/stm32u073kc" ]
1444stm32u073m8 = [ "stm32-metapac/stm32u073m8" ]
1445stm32u073mb = [ "stm32-metapac/stm32u073mb" ]
1446stm32u073mc = [ "stm32-metapac/stm32u073mc" ]
1447stm32u073r8 = [ "stm32-metapac/stm32u073r8" ]
1448stm32u073rb = [ "stm32-metapac/stm32u073rb" ]
1449stm32u073rc = [ "stm32-metapac/stm32u073rc" ]
1450stm32u083cc = [ "stm32-metapac/stm32u083cc" ]
1451stm32u083hc = [ "stm32-metapac/stm32u083hc" ]
1452stm32u083kc = [ "stm32-metapac/stm32u083kc" ]
1453stm32u083mc = [ "stm32-metapac/stm32u083mc" ]
1454stm32u083rc = [ "stm32-metapac/stm32u083rc" ]
1422stm32u535cb = [ "stm32-metapac/stm32u535cb" ] 1455stm32u535cb = [ "stm32-metapac/stm32u535cb" ]
1423stm32u535cc = [ "stm32-metapac/stm32u535cc" ] 1456stm32u535cc = [ "stm32-metapac/stm32u535cc" ]
1424stm32u535ce = [ "stm32-metapac/stm32u535ce" ] 1457stm32u535ce = [ "stm32-metapac/stm32u535ce" ]
@@ -1474,6 +1507,7 @@ stm32u599vj = [ "stm32-metapac/stm32u599vj" ]
1474stm32u599zi = [ "stm32-metapac/stm32u599zi" ] 1507stm32u599zi = [ "stm32-metapac/stm32u599zi" ]
1475stm32u599zj = [ "stm32-metapac/stm32u599zj" ] 1508stm32u599zj = [ "stm32-metapac/stm32u599zj" ]
1476stm32u5a5aj = [ "stm32-metapac/stm32u5a5aj" ] 1509stm32u5a5aj = [ "stm32-metapac/stm32u5a5aj" ]
1510stm32u5a5qi = [ "stm32-metapac/stm32u5a5qi" ]
1477stm32u5a5qj = [ "stm32-metapac/stm32u5a5qj" ] 1511stm32u5a5qj = [ "stm32-metapac/stm32u5a5qj" ]
1478stm32u5a5rj = [ "stm32-metapac/stm32u5a5rj" ] 1512stm32u5a5rj = [ "stm32-metapac/stm32u5a5rj" ]
1479stm32u5a5vj = [ "stm32-metapac/stm32u5a5vj" ] 1513stm32u5a5vj = [ "stm32-metapac/stm32u5a5vj" ]
diff --git a/embassy-stm32/build.rs b/embassy-stm32/build.rs
index 38b6c480c..67fceda56 100644
--- a/embassy-stm32/build.rs
+++ b/embassy-stm32/build.rs
@@ -272,8 +272,6 @@ fn main() {
272 "Bank1" 272 "Bank1"
273 } else if region.name.starts_with("BANK_2") { 273 } else if region.name.starts_with("BANK_2") {
274 "Bank2" 274 "Bank2"
275 } else if region.name == "OTP" {
276 "Otp"
277 } else { 275 } else {
278 continue; 276 continue;
279 } 277 }
@@ -664,6 +662,7 @@ fn main() {
664 #(pub use crate::pac::rcc::vals::#enum_names as #enum_names; )* 662 #(pub use crate::pac::rcc::vals::#enum_names as #enum_names; )*
665 663
666 #[derive(Clone, Copy)] 664 #[derive(Clone, Copy)]
665 #[non_exhaustive]
667 pub struct ClockMux { 666 pub struct ClockMux {
668 #( #struct_fields, )* 667 #( #struct_fields, )*
669 } 668 }
diff --git a/embassy-stm32/src/adc/f1.rs b/embassy-stm32/src/adc/f1.rs
index cecf67947..80eaecc14 100644
--- a/embassy-stm32/src/adc/f1.rs
+++ b/embassy-stm32/src/adc/f1.rs
@@ -3,8 +3,8 @@ use core::marker::PhantomData;
3use core::task::Poll; 3use core::task::Poll;
4 4
5use embassy_hal_internal::into_ref; 5use embassy_hal_internal::into_ref;
6use embedded_hal_02::blocking::delay::DelayUs;
7 6
7use super::blocking_delay_us;
8use crate::adc::{Adc, AdcPin, Instance, SampleTime}; 8use crate::adc::{Adc, AdcPin, Instance, SampleTime};
9use crate::time::Hertz; 9use crate::time::Hertz;
10use crate::{interrupt, Peripheral}; 10use crate::{interrupt, Peripheral};
@@ -48,14 +48,14 @@ impl<T: Instance> super::SealedAdcPin<T> for Temperature {
48} 48}
49 49
50impl<'d, T: Instance> Adc<'d, T> { 50impl<'d, T: Instance> Adc<'d, T> {
51 pub fn new(adc: impl Peripheral<P = T> + 'd, delay: &mut impl DelayUs<u32>) -> Self { 51 pub fn new(adc: impl Peripheral<P = T> + 'd) -> Self {
52 into_ref!(adc); 52 into_ref!(adc);
53 T::enable_and_reset(); 53 T::enable_and_reset();
54 T::regs().cr2().modify(|reg| reg.set_adon(true)); 54 T::regs().cr2().modify(|reg| reg.set_adon(true));
55 55
56 // 11.4: Before starting a calibration, the ADC must have been in power-on state (ADON bit = ‘1’) 56 // 11.4: Before starting a calibration, the ADC must have been in power-on state (ADON bit = ‘1’)
57 // for at least two ADC clock cycles 57 // for at least two ADC clock cycles.
58 delay.delay_us((1_000_000 * 2) / Self::freq().0 + 1); 58 blocking_delay_us((1_000_000 * 2) / Self::freq().0 + 1);
59 59
60 // Reset calibration 60 // Reset calibration
61 T::regs().cr2().modify(|reg| reg.set_rstcal(true)); 61 T::regs().cr2().modify(|reg| reg.set_rstcal(true));
@@ -70,7 +70,7 @@ impl<'d, T: Instance> Adc<'d, T> {
70 } 70 }
71 71
72 // One cycle after calibration 72 // One cycle after calibration
73 delay.delay_us((1_000_000) / Self::freq().0 + 1); 73 blocking_delay_us((1_000_000 * 1) / Self::freq().0 + 1);
74 74
75 Self { 75 Self {
76 adc, 76 adc,
@@ -95,7 +95,7 @@ impl<'d, T: Instance> Adc<'d, T> {
95 } 95 }
96 } 96 }
97 97
98 pub fn enable_vref(&self, _delay: &mut impl DelayUs<u32>) -> Vref { 98 pub fn enable_vref(&self) -> Vref {
99 T::regs().cr2().modify(|reg| { 99 T::regs().cr2().modify(|reg| {
100 reg.set_tsvrefe(true); 100 reg.set_tsvrefe(true);
101 }); 101 });
diff --git a/embassy-stm32/src/adc/f3.rs b/embassy-stm32/src/adc/f3.rs
index c5581dba1..c22a3fe4a 100644
--- a/embassy-stm32/src/adc/f3.rs
+++ b/embassy-stm32/src/adc/f3.rs
@@ -3,8 +3,8 @@ use core::marker::PhantomData;
3use core::task::Poll; 3use core::task::Poll;
4 4
5use embassy_hal_internal::into_ref; 5use embassy_hal_internal::into_ref;
6use embedded_hal_02::blocking::delay::DelayUs;
7 6
7use super::blocking_delay_us;
8use crate::adc::{Adc, AdcPin, Instance, SampleTime}; 8use crate::adc::{Adc, AdcPin, Instance, SampleTime};
9use crate::interrupt::typelevel::Interrupt; 9use crate::interrupt::typelevel::Interrupt;
10use crate::time::Hertz; 10use crate::time::Hertz;
@@ -58,7 +58,6 @@ impl<'d, T: Instance> Adc<'d, T> {
58 pub fn new( 58 pub fn new(
59 adc: impl Peripheral<P = T> + 'd, 59 adc: impl Peripheral<P = T> + 'd,
60 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, 60 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
61 delay: &mut impl DelayUs<u32>,
62 ) -> Self { 61 ) -> Self {
63 use crate::pac::adc::vals; 62 use crate::pac::adc::vals;
64 63
@@ -71,7 +70,7 @@ impl<'d, T: Instance> Adc<'d, T> {
71 T::regs().cr().modify(|w| w.set_advregen(vals::Advregen::ENABLED)); 70 T::regs().cr().modify(|w| w.set_advregen(vals::Advregen::ENABLED));
72 71
73 // Wait for the regulator to stabilize 72 // Wait for the regulator to stabilize
74 delay.delay_us(10); 73 blocking_delay_us(10);
75 74
76 assert!(!T::regs().cr().read().aden()); 75 assert!(!T::regs().cr().read().aden());
77 76
@@ -81,8 +80,8 @@ impl<'d, T: Instance> Adc<'d, T> {
81 80
82 while T::regs().cr().read().adcal() {} 81 while T::regs().cr().read().adcal() {}
83 82
84 // Wait more than 4 clock cycles after adcal is cleared (RM0364 p. 223) 83 // Wait more than 4 clock cycles after adcal is cleared (RM0364 p. 223).
85 delay.delay_us(1 + (6 * 1_000_000 / Self::freq().0)); 84 blocking_delay_us((1_000_000 * 4) / Self::freq().0 + 1);
86 85
87 // Enable the adc 86 // Enable the adc
88 T::regs().cr().modify(|w| w.set_aden(true)); 87 T::regs().cr().modify(|w| w.set_aden(true));
@@ -117,7 +116,7 @@ impl<'d, T: Instance> Adc<'d, T> {
117 } 116 }
118 } 117 }
119 118
120 pub fn enable_vref(&self, _delay: &mut impl DelayUs<u32>) -> Vref { 119 pub fn enable_vref(&self) -> Vref {
121 T::common_regs().ccr().modify(|w| w.set_vrefen(true)); 120 T::common_regs().ccr().modify(|w| w.set_vrefen(true));
122 121
123 Vref {} 122 Vref {}
diff --git a/embassy-stm32/src/adc/g4.rs b/embassy-stm32/src/adc/g4.rs
new file mode 100644
index 000000000..f6741f019
--- /dev/null
+++ b/embassy-stm32/src/adc/g4.rs
@@ -0,0 +1,304 @@
1#[allow(unused)]
2use pac::adc::vals::{Adcaldif, Difsel, Exten};
3use pac::adccommon::vals::Presc;
4
5use super::{blocking_delay_us, Adc, AdcPin, Instance, InternalChannel, Resolution, SampleTime};
6use crate::time::Hertz;
7use crate::{pac, Peripheral};
8
9/// Default VREF voltage used for sample conversion to millivolts.
10pub const VREF_DEFAULT_MV: u32 = 3300;
11/// VREF voltage used for factory calibration of VREFINTCAL register.
12pub const VREF_CALIB_MV: u32 = 3300;
13
14/// Max single ADC operation clock frequency
15#[cfg(stm32g4)]
16const MAX_ADC_CLK_FREQ: Hertz = Hertz::mhz(60);
17#[cfg(stm32h7)]
18const MAX_ADC_CLK_FREQ: Hertz = Hertz::mhz(50);
19
20#[cfg(stm32g4)]
21const VREF_CHANNEL: u8 = 18;
22#[cfg(stm32g4)]
23const TEMP_CHANNEL: u8 = 16;
24
25#[cfg(stm32h7)]
26const VREF_CHANNEL: u8 = 19;
27#[cfg(stm32h7)]
28const TEMP_CHANNEL: u8 = 18;
29
30// TODO this should be 14 for H7a/b/35
31const VBAT_CHANNEL: u8 = 17;
32
33// NOTE: Vrefint/Temperature/Vbat are not available on all ADCs, this currently cannot be modeled with stm32-data, so these are available from the software on all ADCs
34/// Internal voltage reference channel.
35pub struct VrefInt;
36impl<T: Instance> InternalChannel<T> for VrefInt {}
37impl<T: Instance> super::SealedInternalChannel<T> for VrefInt {
38 fn channel(&self) -> u8 {
39 VREF_CHANNEL
40 }
41}
42
43/// Internal temperature channel.
44pub struct Temperature;
45impl<T: Instance> InternalChannel<T> for Temperature {}
46impl<T: Instance> super::SealedInternalChannel<T> for Temperature {
47 fn channel(&self) -> u8 {
48 TEMP_CHANNEL
49 }
50}
51
52/// Internal battery voltage channel.
53pub struct Vbat;
54impl<T: Instance> InternalChannel<T> for Vbat {}
55impl<T: Instance> super::SealedInternalChannel<T> for Vbat {
56 fn channel(&self) -> u8 {
57 VBAT_CHANNEL
58 }
59}
60
61// NOTE (unused): The prescaler enum closely copies the hardware capabilities,
62// but high prescaling doesn't make a lot of sense in the current implementation and is ommited.
63#[allow(unused)]
64enum Prescaler {
65 NotDivided,
66 DividedBy2,
67 DividedBy4,
68 DividedBy6,
69 DividedBy8,
70 DividedBy10,
71 DividedBy12,
72 DividedBy16,
73 DividedBy32,
74 DividedBy64,
75 DividedBy128,
76 DividedBy256,
77}
78
79impl Prescaler {
80 fn from_ker_ck(frequency: Hertz) -> Self {
81 let raw_prescaler = frequency.0 / MAX_ADC_CLK_FREQ.0;
82 match raw_prescaler {
83 0 => Self::NotDivided,
84 1 => Self::DividedBy2,
85 2..=3 => Self::DividedBy4,
86 4..=5 => Self::DividedBy6,
87 6..=7 => Self::DividedBy8,
88 8..=9 => Self::DividedBy10,
89 10..=11 => Self::DividedBy12,
90 _ => unimplemented!(),
91 }
92 }
93
94 fn divisor(&self) -> u32 {
95 match self {
96 Prescaler::NotDivided => 1,
97 Prescaler::DividedBy2 => 2,
98 Prescaler::DividedBy4 => 4,
99 Prescaler::DividedBy6 => 6,
100 Prescaler::DividedBy8 => 8,
101 Prescaler::DividedBy10 => 10,
102 Prescaler::DividedBy12 => 12,
103 Prescaler::DividedBy16 => 16,
104 Prescaler::DividedBy32 => 32,
105 Prescaler::DividedBy64 => 64,
106 Prescaler::DividedBy128 => 128,
107 Prescaler::DividedBy256 => 256,
108 }
109 }
110
111 fn presc(&self) -> Presc {
112 match self {
113 Prescaler::NotDivided => Presc::DIV1,
114 Prescaler::DividedBy2 => Presc::DIV2,
115 Prescaler::DividedBy4 => Presc::DIV4,
116 Prescaler::DividedBy6 => Presc::DIV6,
117 Prescaler::DividedBy8 => Presc::DIV8,
118 Prescaler::DividedBy10 => Presc::DIV10,
119 Prescaler::DividedBy12 => Presc::DIV12,
120 Prescaler::DividedBy16 => Presc::DIV16,
121 Prescaler::DividedBy32 => Presc::DIV32,
122 Prescaler::DividedBy64 => Presc::DIV64,
123 Prescaler::DividedBy128 => Presc::DIV128,
124 Prescaler::DividedBy256 => Presc::DIV256,
125 }
126 }
127}
128
129impl<'d, T: Instance> Adc<'d, T> {
130 /// Create a new ADC driver.
131 pub fn new(adc: impl Peripheral<P = T> + 'd) -> Self {
132 embassy_hal_internal::into_ref!(adc);
133 T::enable_and_reset();
134
135 let prescaler = Prescaler::from_ker_ck(T::frequency());
136
137 T::common_regs().ccr().modify(|w| w.set_presc(prescaler.presc()));
138
139 let frequency = Hertz(T::frequency().0 / prescaler.divisor());
140 info!("ADC frequency set to {} Hz", frequency.0);
141
142 if frequency > MAX_ADC_CLK_FREQ {
143 panic!("Maximal allowed frequency for the ADC is {} MHz and it varies with different packages, refer to ST docs for more information.", MAX_ADC_CLK_FREQ.0 / 1_000_000 );
144 }
145
146 let mut s = Self {
147 adc,
148 sample_time: SampleTime::from_bits(0),
149 };
150 s.power_up();
151 s.configure_differential_inputs();
152
153 s.calibrate();
154 blocking_delay_us(1);
155
156 s.enable();
157 s.configure();
158
159 s
160 }
161
162 fn power_up(&mut self) {
163 T::regs().cr().modify(|reg| {
164 reg.set_deeppwd(false);
165 reg.set_advregen(true);
166 });
167
168 blocking_delay_us(10);
169 }
170
171 fn configure_differential_inputs(&mut self) {
172 T::regs().difsel().modify(|w| {
173 for n in 0..20 {
174 w.set_difsel(n, Difsel::SINGLEENDED);
175 }
176 });
177 }
178
179 fn calibrate(&mut self) {
180 T::regs().cr().modify(|w| {
181 w.set_adcaldif(Adcaldif::SINGLEENDED);
182 });
183
184 T::regs().cr().modify(|w| w.set_adcal(true));
185
186 while T::regs().cr().read().adcal() {}
187 }
188
189 fn enable(&mut self) {
190 T::regs().isr().write(|w| w.set_adrdy(true));
191 T::regs().cr().modify(|w| w.set_aden(true));
192 while !T::regs().isr().read().adrdy() {}
193 T::regs().isr().write(|w| w.set_adrdy(true));
194 }
195
196 fn configure(&mut self) {
197 // single conversion mode, software trigger
198 T::regs().cfgr().modify(|w| {
199 w.set_cont(false);
200 w.set_exten(Exten::DISABLED);
201 });
202 }
203
204 /// Enable reading the voltage reference internal channel.
205 pub fn enable_vrefint(&self) -> VrefInt {
206 T::common_regs().ccr().modify(|reg| {
207 reg.set_vrefen(true);
208 });
209
210 VrefInt {}
211 }
212
213 /// Enable reading the temperature internal channel.
214 pub fn enable_temperature(&self) -> Temperature {
215 T::common_regs().ccr().modify(|reg| {
216 reg.set_vsenseen(true);
217 });
218
219 Temperature {}
220 }
221
222 /// Enable reading the vbat internal channel.
223 pub fn enable_vbat(&self) -> Vbat {
224 T::common_regs().ccr().modify(|reg| {
225 reg.set_vbaten(true);
226 });
227
228 Vbat {}
229 }
230
231 /// Set the ADC sample time.
232 pub fn set_sample_time(&mut self, sample_time: SampleTime) {
233 self.sample_time = sample_time;
234 }
235
236 /// Set the ADC resolution.
237 pub fn set_resolution(&mut self, resolution: Resolution) {
238 T::regs().cfgr().modify(|reg| reg.set_res(resolution.into()));
239 }
240
241 /// Perform a single conversion.
242 fn convert(&mut self) -> u16 {
243 T::regs().isr().modify(|reg| {
244 reg.set_eos(true);
245 reg.set_eoc(true);
246 });
247
248 // Start conversion
249 T::regs().cr().modify(|reg| {
250 reg.set_adstart(true);
251 });
252
253 while !T::regs().isr().read().eos() {
254 // spin
255 }
256
257 T::regs().dr().read().0 as u16
258 }
259
260 /// Read an ADC pin.
261 pub fn read<P>(&mut self, pin: &mut P) -> u16
262 where
263 P: AdcPin<T>,
264 P: crate::gpio::Pin,
265 {
266 pin.set_as_analog();
267
268 self.read_channel(pin.channel())
269 }
270
271 /// Read an ADC internal channel.
272 pub fn read_internal(&mut self, channel: &mut impl InternalChannel<T>) -> u16 {
273 self.read_channel(channel.channel())
274 }
275
276 fn read_channel(&mut self, channel: u8) -> u16 {
277 // Configure channel
278 Self::set_channel_sample_time(channel, self.sample_time);
279
280 #[cfg(stm32h7)]
281 {
282 T::regs().cfgr2().modify(|w| w.set_lshift(0));
283 T::regs()
284 .pcsel()
285 .write(|w| w.set_pcsel(channel as _, Pcsel::PRESELECTED));
286 }
287
288 T::regs().sqr1().write(|reg| {
289 reg.set_sq(0, channel);
290 reg.set_l(0);
291 });
292
293 self.convert()
294 }
295
296 fn set_channel_sample_time(ch: u8, sample_time: SampleTime) {
297 let sample_time = sample_time.into();
298 if ch <= 9 {
299 T::regs().smpr().modify(|reg| reg.set_smp(ch as _, sample_time));
300 } else {
301 T::regs().smpr2().modify(|reg| reg.set_smp((ch - 10) as _, sample_time));
302 }
303 }
304}
diff --git a/embassy-stm32/src/adc/mod.rs b/embassy-stm32/src/adc/mod.rs
index ead2357ce..12c5751bd 100644
--- a/embassy-stm32/src/adc/mod.rs
+++ b/embassy-stm32/src/adc/mod.rs
@@ -12,6 +12,7 @@
12#[cfg_attr(adc_v2, path = "v2.rs")] 12#[cfg_attr(adc_v2, path = "v2.rs")]
13#[cfg_attr(any(adc_v3, adc_g0, adc_h5), path = "v3.rs")] 13#[cfg_attr(any(adc_v3, adc_g0, adc_h5), path = "v3.rs")]
14#[cfg_attr(adc_v4, path = "v4.rs")] 14#[cfg_attr(adc_v4, path = "v4.rs")]
15#[cfg_attr(adc_g4, path = "g4.rs")]
15mod _version; 16mod _version;
16 17
17#[allow(unused)] 18#[allow(unused)]
@@ -69,14 +70,47 @@ trait SealedInternalChannel<T> {
69 fn channel(&self) -> u8; 70 fn channel(&self) -> u8;
70} 71}
71 72
73/// Performs a busy-wait delay for a specified number of microseconds.
74#[allow(unused)]
75pub(crate) fn blocking_delay_us(us: u32) {
76 #[cfg(time)]
77 embassy_time::block_for(embassy_time::Duration::from_micros(us));
78 #[cfg(not(time))]
79 cortex_m::asm::delay(unsafe { crate::rcc::get_freqs() }.sys.unwrap().0 * us / 1_000_000);
80}
81
72/// ADC instance. 82/// ADC instance.
73#[cfg(not(any(adc_f1, adc_v1, adc_l0, adc_v2, adc_v3, adc_v4, adc_f3, adc_f3_v1_1, adc_g0, adc_h5)))] 83#[cfg(not(any(
84 adc_f1,
85 adc_v1,
86 adc_l0,
87 adc_v2,
88 adc_v3,
89 adc_v4,
90 adc_g4,
91 adc_f3,
92 adc_f3_v1_1,
93 adc_g0,
94 adc_h5
95)))]
74#[allow(private_bounds)] 96#[allow(private_bounds)]
75pub trait Instance: SealedInstance + crate::Peripheral<P = Self> { 97pub trait Instance: SealedInstance + crate::Peripheral<P = Self> {
76 type Interrupt: crate::interrupt::typelevel::Interrupt; 98 type Interrupt: crate::interrupt::typelevel::Interrupt;
77} 99}
78/// ADC instance. 100/// ADC instance.
79#[cfg(any(adc_f1, adc_v1, adc_l0, adc_v2, adc_v3, adc_v4, adc_f3, adc_f3_v1_1, adc_g0, adc_h5))] 101#[cfg(any(
102 adc_f1,
103 adc_v1,
104 adc_l0,
105 adc_v2,
106 adc_v3,
107 adc_v4,
108 adc_g4,
109 adc_f3,
110 adc_f3_v1_1,
111 adc_g0,
112 adc_h5
113))]
80#[allow(private_bounds)] 114#[allow(private_bounds)]
81pub trait Instance: SealedInstance + crate::Peripheral<P = Self> + crate::rcc::RccPeripheral { 115pub trait Instance: SealedInstance + crate::Peripheral<P = Self> + crate::rcc::RccPeripheral {
82 type Interrupt: crate::interrupt::typelevel::Interrupt; 116 type Interrupt: crate::interrupt::typelevel::Interrupt;
diff --git a/embassy-stm32/src/adc/v1.rs b/embassy-stm32/src/adc/v1.rs
index e9b46be80..1dda28cf2 100644
--- a/embassy-stm32/src/adc/v1.rs
+++ b/embassy-stm32/src/adc/v1.rs
@@ -3,10 +3,10 @@ use core::marker::PhantomData;
3use core::task::Poll; 3use core::task::Poll;
4 4
5use embassy_hal_internal::into_ref; 5use embassy_hal_internal::into_ref;
6use embedded_hal_02::blocking::delay::DelayUs;
7#[cfg(adc_l0)] 6#[cfg(adc_l0)]
8use stm32_metapac::adc::vals::Ckmode; 7use stm32_metapac::adc::vals::Ckmode;
9 8
9use super::blocking_delay_us;
10use crate::adc::{Adc, AdcPin, Instance, Resolution, SampleTime}; 10use crate::adc::{Adc, AdcPin, Instance, Resolution, SampleTime};
11use crate::interrupt::typelevel::Interrupt; 11use crate::interrupt::typelevel::Interrupt;
12use crate::peripherals::ADC; 12use crate::peripherals::ADC;
@@ -65,7 +65,6 @@ impl<'d, T: Instance> Adc<'d, T> {
65 pub fn new( 65 pub fn new(
66 adc: impl Peripheral<P = T> + 'd, 66 adc: impl Peripheral<P = T> + 'd,
67 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, 67 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
68 delay: &mut impl DelayUs<u32>,
69 ) -> Self { 68 ) -> Self {
70 into_ref!(adc); 69 into_ref!(adc);
71 T::enable_and_reset(); 70 T::enable_and_reset();
@@ -74,7 +73,7 @@ impl<'d, T: Instance> Adc<'d, T> {
74 // 73 //
75 // Table 57. ADC characteristics 74 // Table 57. ADC characteristics
76 // tstab = 14 * 1/fadc 75 // tstab = 14 * 1/fadc
77 delay.delay_us(1); 76 blocking_delay_us(1);
78 77
79 // set default PCKL/2 on L0s because HSI is disabled in the default clock config 78 // set default PCKL/2 on L0s because HSI is disabled in the default clock config
80 #[cfg(adc_l0)] 79 #[cfg(adc_l0)]
@@ -114,7 +113,7 @@ impl<'d, T: Instance> Adc<'d, T> {
114 } 113 }
115 114
116 #[cfg(not(adc_l0))] 115 #[cfg(not(adc_l0))]
117 pub fn enable_vbat(&self, _delay: &mut impl DelayUs<u32>) -> Vbat { 116 pub fn enable_vbat(&self) -> Vbat {
118 // SMP must be ≥ 56 ADC clock cycles when using HSI14. 117 // SMP must be ≥ 56 ADC clock cycles when using HSI14.
119 // 118 //
120 // 6.3.20 Vbat monitoring characteristics 119 // 6.3.20 Vbat monitoring characteristics
@@ -123,22 +122,22 @@ impl<'d, T: Instance> Adc<'d, T> {
123 Vbat 122 Vbat
124 } 123 }
125 124
126 pub fn enable_vref(&self, delay: &mut impl DelayUs<u32>) -> Vref { 125 pub fn enable_vref(&self) -> Vref {
127 // Table 28. Embedded internal reference voltage 126 // Table 28. Embedded internal reference voltage
128 // tstart = 10μs 127 // tstart = 10μs
129 T::regs().ccr().modify(|reg| reg.set_vrefen(true)); 128 T::regs().ccr().modify(|reg| reg.set_vrefen(true));
130 delay.delay_us(10); 129 blocking_delay_us(10);
131 Vref 130 Vref
132 } 131 }
133 132
134 pub fn enable_temperature(&self, delay: &mut impl DelayUs<u32>) -> Temperature { 133 pub fn enable_temperature(&self) -> Temperature {
135 // SMP must be ≥ 56 ADC clock cycles when using HSI14. 134 // SMP must be ≥ 56 ADC clock cycles when using HSI14.
136 // 135 //
137 // 6.3.19 Temperature sensor characteristics 136 // 6.3.19 Temperature sensor characteristics
138 // tstart ≤ 10μs 137 // tstart ≤ 10μs
139 // ts_temp ≥ 4μs 138 // ts_temp ≥ 4μs
140 T::regs().ccr().modify(|reg| reg.set_tsen(true)); 139 T::regs().ccr().modify(|reg| reg.set_tsen(true));
141 delay.delay_us(10); 140 blocking_delay_us(10);
142 Temperature 141 Temperature
143 } 142 }
144 143
diff --git a/embassy-stm32/src/adc/v2.rs b/embassy-stm32/src/adc/v2.rs
index a43eb72db..7771cf768 100644
--- a/embassy-stm32/src/adc/v2.rs
+++ b/embassy-stm32/src/adc/v2.rs
@@ -1,6 +1,6 @@
1use embassy_hal_internal::into_ref; 1use embassy_hal_internal::into_ref;
2use embedded_hal_02::blocking::delay::DelayUs;
3 2
3use super::blocking_delay_us;
4use crate::adc::{Adc, AdcPin, Instance, Resolution, SampleTime}; 4use crate::adc::{Adc, AdcPin, Instance, Resolution, SampleTime};
5use crate::peripherals::ADC1; 5use crate::peripherals::ADC1;
6use crate::time::Hertz; 6use crate::time::Hertz;
@@ -11,9 +11,6 @@ pub const VREF_DEFAULT_MV: u32 = 3300;
11/// VREF voltage used for factory calibration of VREFINTCAL register. 11/// VREF voltage used for factory calibration of VREFINTCAL register.
12pub const VREF_CALIB_MV: u32 = 3300; 12pub const VREF_CALIB_MV: u32 = 3300;
13 13
14/// ADC turn-on time
15pub const ADC_POWERUP_TIME_US: u32 = 3;
16
17pub struct VrefInt; 14pub struct VrefInt;
18impl AdcPin<ADC1> for VrefInt {} 15impl AdcPin<ADC1> for VrefInt {}
19impl super::SealedAdcPin<ADC1> for VrefInt { 16impl super::SealedAdcPin<ADC1> for VrefInt {
@@ -97,7 +94,7 @@ impl<'d, T> Adc<'d, T>
97where 94where
98 T: Instance, 95 T: Instance,
99{ 96{
100 pub fn new(adc: impl Peripheral<P = T> + 'd, delay: &mut impl DelayUs<u32>) -> Self { 97 pub fn new(adc: impl Peripheral<P = T> + 'd) -> Self {
101 into_ref!(adc); 98 into_ref!(adc);
102 T::enable_and_reset(); 99 T::enable_and_reset();
103 100
@@ -107,7 +104,7 @@ where
107 reg.set_adon(true); 104 reg.set_adon(true);
108 }); 105 });
109 106
110 delay.delay_us(ADC_POWERUP_TIME_US); 107 blocking_delay_us(3);
111 108
112 Self { 109 Self {
113 adc, 110 adc,
diff --git a/embassy-stm32/src/adc/v3.rs b/embassy-stm32/src/adc/v3.rs
index 8c9b47197..4fd8558ba 100644
--- a/embassy-stm32/src/adc/v3.rs
+++ b/embassy-stm32/src/adc/v3.rs
@@ -1,7 +1,7 @@
1use cfg_if::cfg_if; 1use cfg_if::cfg_if;
2use embassy_hal_internal::into_ref; 2use embassy_hal_internal::into_ref;
3use embedded_hal_02::blocking::delay::DelayUs;
4 3
4use super::blocking_delay_us;
5use crate::adc::{Adc, AdcPin, Instance, Resolution, SampleTime}; 5use crate::adc::{Adc, AdcPin, Instance, Resolution, SampleTime};
6use crate::Peripheral; 6use crate::Peripheral;
7 7
@@ -74,7 +74,7 @@ cfg_if! {
74} 74}
75 75
76impl<'d, T: Instance> Adc<'d, T> { 76impl<'d, T: Instance> Adc<'d, T> {
77 pub fn new(adc: impl Peripheral<P = T> + 'd, delay: &mut impl DelayUs<u32>) -> Self { 77 pub fn new(adc: impl Peripheral<P = T> + 'd) -> Self {
78 into_ref!(adc); 78 into_ref!(adc);
79 T::enable_and_reset(); 79 T::enable_and_reset();
80 T::regs().cr().modify(|reg| { 80 T::regs().cr().modify(|reg| {
@@ -88,7 +88,7 @@ impl<'d, T: Instance> Adc<'d, T> {
88 reg.set_chselrmod(false); 88 reg.set_chselrmod(false);
89 }); 89 });
90 90
91 delay.delay_us(20); 91 blocking_delay_us(20);
92 92
93 T::regs().cr().modify(|reg| { 93 T::regs().cr().modify(|reg| {
94 reg.set_adcal(true); 94 reg.set_adcal(true);
@@ -98,7 +98,7 @@ impl<'d, T: Instance> Adc<'d, T> {
98 // spin 98 // spin
99 } 99 }
100 100
101 delay.delay_us(1); 101 blocking_delay_us(1);
102 102
103 Self { 103 Self {
104 adc, 104 adc,
@@ -106,7 +106,7 @@ impl<'d, T: Instance> Adc<'d, T> {
106 } 106 }
107 } 107 }
108 108
109 pub fn enable_vrefint(&self, delay: &mut impl DelayUs<u32>) -> VrefInt { 109 pub fn enable_vrefint(&self) -> VrefInt {
110 #[cfg(not(adc_g0))] 110 #[cfg(not(adc_g0))]
111 T::common_regs().ccr().modify(|reg| { 111 T::common_regs().ccr().modify(|reg| {
112 reg.set_vrefen(true); 112 reg.set_vrefen(true);
@@ -117,10 +117,8 @@ impl<'d, T: Instance> Adc<'d, T> {
117 }); 117 });
118 118
119 // "Table 24. Embedded internal voltage reference" states that it takes a maximum of 12 us 119 // "Table 24. Embedded internal voltage reference" states that it takes a maximum of 12 us
120 // to stabilize the internal voltage reference, we wait a little more. 120 // to stabilize the internal voltage reference.
121 // TODO: delay 15us 121 blocking_delay_us(15);
122 //cortex_m::asm::delay(20_000_000);
123 delay.delay_us(15);
124 122
125 VrefInt {} 123 VrefInt {}
126 } 124 }
@@ -222,6 +220,13 @@ impl<'d, T: Instance> Adc<'d, T> {
222 // spin 220 // spin
223 } 221 }
224 222
223 // RM0492, RM0481, etc.
224 // "This option bit must be set to 1 when ADCx_INP0 or ADCx_INN1 channel is selected."
225 #[cfg(adc_h5)]
226 if pin.channel() == 0 {
227 T::regs().or().modify(|reg| reg.set_op0(true));
228 }
229
225 // Configure channel 230 // Configure channel
226 Self::set_channel_sample_time(pin.channel(), self.sample_time); 231 Self::set_channel_sample_time(pin.channel(), self.sample_time);
227 232
@@ -244,6 +249,13 @@ impl<'d, T: Instance> Adc<'d, T> {
244 249
245 T::regs().cr().modify(|reg| reg.set_addis(true)); 250 T::regs().cr().modify(|reg| reg.set_addis(true));
246 251
252 // RM0492, RM0481, etc.
253 // "This option bit must be set to 1 when ADCx_INP0 or ADCx_INN1 channel is selected."
254 #[cfg(adc_h5)]
255 if pin.channel() == 0 {
256 T::regs().or().modify(|reg| reg.set_op0(false));
257 }
258
247 val 259 val
248 } 260 }
249 261
diff --git a/embassy-stm32/src/adc/v4.rs b/embassy-stm32/src/adc/v4.rs
index 1ae25bea2..ca87b41ee 100644
--- a/embassy-stm32/src/adc/v4.rs
+++ b/embassy-stm32/src/adc/v4.rs
@@ -1,9 +1,8 @@
1use embedded_hal_02::blocking::delay::DelayUs;
2#[allow(unused)] 1#[allow(unused)]
3use pac::adc::vals::{Adcaldif, Boost, Difsel, Exten, Pcsel}; 2use pac::adc::vals::{Adcaldif, Boost, Difsel, Exten, Pcsel};
4use pac::adccommon::vals::Presc; 3use pac::adccommon::vals::Presc;
5 4
6use super::{Adc, AdcPin, Instance, InternalChannel, Resolution, SampleTime}; 5use super::{blocking_delay_us, Adc, AdcPin, Instance, InternalChannel, Resolution, SampleTime};
7use crate::time::Hertz; 6use crate::time::Hertz;
8use crate::{pac, Peripheral}; 7use crate::{pac, Peripheral};
9 8
@@ -129,7 +128,7 @@ impl Prescaler {
129 128
130impl<'d, T: Instance> Adc<'d, T> { 129impl<'d, T: Instance> Adc<'d, T> {
131 /// Create a new ADC driver. 130 /// Create a new ADC driver.
132 pub fn new(adc: impl Peripheral<P = T> + 'd, delay: &mut impl DelayUs<u16>) -> Self { 131 pub fn new(adc: impl Peripheral<P = T> + 'd) -> Self {
133 embassy_hal_internal::into_ref!(adc); 132 embassy_hal_internal::into_ref!(adc);
134 T::enable_and_reset(); 133 T::enable_and_reset();
135 134
@@ -161,11 +160,11 @@ impl<'d, T: Instance> Adc<'d, T> {
161 adc, 160 adc,
162 sample_time: SampleTime::from_bits(0), 161 sample_time: SampleTime::from_bits(0),
163 }; 162 };
164 s.power_up(delay); 163 s.power_up();
165 s.configure_differential_inputs(); 164 s.configure_differential_inputs();
166 165
167 s.calibrate(); 166 s.calibrate();
168 delay.delay_us(1); 167 blocking_delay_us(1);
169 168
170 s.enable(); 169 s.enable();
171 s.configure(); 170 s.configure();
@@ -173,13 +172,13 @@ impl<'d, T: Instance> Adc<'d, T> {
173 s 172 s
174 } 173 }
175 174
176 fn power_up(&mut self, delay: &mut impl DelayUs<u16>) { 175 fn power_up(&mut self) {
177 T::regs().cr().modify(|reg| { 176 T::regs().cr().modify(|reg| {
178 reg.set_deeppwd(false); 177 reg.set_deeppwd(false);
179 reg.set_advregen(true); 178 reg.set_advregen(true);
180 }); 179 });
181 180
182 delay.delay_us(10); 181 blocking_delay_us(10);
183 } 182 }
184 183
185 fn configure_differential_inputs(&mut self) { 184 fn configure_differential_inputs(&mut self) {
diff --git a/embassy-stm32/src/crc/v1.rs b/embassy-stm32/src/crc/v1.rs
index f8909d438..e8e0270af 100644
--- a/embassy-stm32/src/crc/v1.rs
+++ b/embassy-stm32/src/crc/v1.rs
@@ -32,6 +32,9 @@ impl<'d> Crc<'d> {
32 /// Feeds a word to the peripheral and returns the current CRC value 32 /// Feeds a word to the peripheral and returns the current CRC value
33 pub fn feed_word(&mut self, word: u32) -> u32 { 33 pub fn feed_word(&mut self, word: u32) -> u32 {
34 // write a single byte to the device, and return the result 34 // write a single byte to the device, and return the result
35 #[cfg(not(crc_v1))]
36 PAC_CRC.dr32().write_value(word);
37 #[cfg(crc_v1)]
35 PAC_CRC.dr().write_value(word); 38 PAC_CRC.dr().write_value(word);
36 self.read() 39 self.read()
37 } 40 }
@@ -39,6 +42,9 @@ impl<'d> Crc<'d> {
39 /// Feed a slice of words to the peripheral and return the result. 42 /// Feed a slice of words to the peripheral and return the result.
40 pub fn feed_words(&mut self, words: &[u32]) -> u32 { 43 pub fn feed_words(&mut self, words: &[u32]) -> u32 {
41 for word in words { 44 for word in words {
45 #[cfg(not(crc_v1))]
46 PAC_CRC.dr32().write_value(*word);
47 #[cfg(crc_v1)]
42 PAC_CRC.dr().write_value(*word); 48 PAC_CRC.dr().write_value(*word);
43 } 49 }
44 50
@@ -46,6 +52,12 @@ impl<'d> Crc<'d> {
46 } 52 }
47 53
48 /// Read the CRC result value. 54 /// Read the CRC result value.
55 #[cfg(not(crc_v1))]
56 pub fn read(&self) -> u32 {
57 PAC_CRC.dr32().read()
58 }
59 /// Read the CRC result value.
60 #[cfg(crc_v1)]
49 pub fn read(&self) -> u32 { 61 pub fn read(&self) -> u32 {
50 PAC_CRC.dr().read() 62 PAC_CRC.dr().read()
51 } 63 }
diff --git a/embassy-stm32/src/crc/v2v3.rs b/embassy-stm32/src/crc/v2v3.rs
index 46f5ea1be..13fb6778c 100644
--- a/embassy-stm32/src/crc/v2v3.rs
+++ b/embassy-stm32/src/crc/v2v3.rs
@@ -136,7 +136,7 @@ impl<'d> Crc<'d> {
136 /// Feeds a byte into the CRC peripheral. Returns the computed checksum. 136 /// Feeds a byte into the CRC peripheral. Returns the computed checksum.
137 pub fn feed_byte(&mut self, byte: u8) -> u32 { 137 pub fn feed_byte(&mut self, byte: u8) -> u32 {
138 PAC_CRC.dr8().write_value(byte); 138 PAC_CRC.dr8().write_value(byte);
139 PAC_CRC.dr().read() 139 PAC_CRC.dr32().read()
140 } 140 }
141 141
142 /// Feeds an slice of bytes into the CRC peripheral. Returns the computed checksum. 142 /// Feeds an slice of bytes into the CRC peripheral. Returns the computed checksum.
@@ -144,30 +144,30 @@ impl<'d> Crc<'d> {
144 for byte in bytes { 144 for byte in bytes {
145 PAC_CRC.dr8().write_value(*byte); 145 PAC_CRC.dr8().write_value(*byte);
146 } 146 }
147 PAC_CRC.dr().read() 147 PAC_CRC.dr32().read()
148 } 148 }
149 /// Feeds a halfword into the CRC peripheral. Returns the computed checksum. 149 /// Feeds a halfword into the CRC peripheral. Returns the computed checksum.
150 pub fn feed_halfword(&mut self, halfword: u16) -> u32 { 150 pub fn feed_halfword(&mut self, halfword: u16) -> u32 {
151 PAC_CRC.dr16().write_value(halfword); 151 PAC_CRC.dr16().write_value(halfword);
152 PAC_CRC.dr().read() 152 PAC_CRC.dr32().read()
153 } 153 }
154 /// Feeds an slice of halfwords into the CRC peripheral. Returns the computed checksum. 154 /// Feeds an slice of halfwords into the CRC peripheral. Returns the computed checksum.
155 pub fn feed_halfwords(&mut self, halfwords: &[u16]) -> u32 { 155 pub fn feed_halfwords(&mut self, halfwords: &[u16]) -> u32 {
156 for halfword in halfwords { 156 for halfword in halfwords {
157 PAC_CRC.dr16().write_value(*halfword); 157 PAC_CRC.dr16().write_value(*halfword);
158 } 158 }
159 PAC_CRC.dr().read() 159 PAC_CRC.dr32().read()
160 } 160 }
161 /// Feeds a words into the CRC peripheral. Returns the computed checksum. 161 /// Feeds a words into the CRC peripheral. Returns the computed checksum.
162 pub fn feed_word(&mut self, word: u32) -> u32 { 162 pub fn feed_word(&mut self, word: u32) -> u32 {
163 PAC_CRC.dr().write_value(word as u32); 163 PAC_CRC.dr32().write_value(word as u32);
164 PAC_CRC.dr().read() 164 PAC_CRC.dr32().read()
165 } 165 }
166 /// Feeds an slice of words into the CRC peripheral. Returns the computed checksum. 166 /// Feeds an slice of words into the CRC peripheral. Returns the computed checksum.
167 pub fn feed_words(&mut self, words: &[u32]) -> u32 { 167 pub fn feed_words(&mut self, words: &[u32]) -> u32 {
168 for word in words { 168 for word in words {
169 PAC_CRC.dr().write_value(*word as u32); 169 PAC_CRC.dr32().write_value(*word as u32);
170 } 170 }
171 PAC_CRC.dr().read() 171 PAC_CRC.dr32().read()
172 } 172 }
173} 173}
diff --git a/embassy-stm32/src/exti.rs b/embassy-stm32/src/exti.rs
index 8d5dae436..224d51b84 100644
--- a/embassy-stm32/src/exti.rs
+++ b/embassy-stm32/src/exti.rs
@@ -27,11 +27,11 @@ fn cpu_regs() -> pac::exti::Exti {
27 EXTI 27 EXTI
28} 28}
29 29
30#[cfg(not(any(exti_c0, exti_g0, exti_l5, gpio_v1, exti_u5, exti_h5, exti_h50)))] 30#[cfg(not(any(exti_c0, exti_g0, exti_u0, exti_l5, gpio_v1, exti_u5, exti_h5, exti_h50)))]
31fn exticr_regs() -> pac::syscfg::Syscfg { 31fn exticr_regs() -> pac::syscfg::Syscfg {
32 pac::SYSCFG 32 pac::SYSCFG
33} 33}
34#[cfg(any(exti_c0, exti_g0, exti_l5, exti_u5, exti_h5, exti_h50))] 34#[cfg(any(exti_c0, exti_g0, exti_u0, exti_l5, exti_u5, exti_h5, exti_h50))]
35fn exticr_regs() -> pac::exti::Exti { 35fn exticr_regs() -> pac::exti::Exti {
36 EXTI 36 EXTI
37} 37}
@@ -44,9 +44,9 @@ unsafe fn on_irq() {
44 #[cfg(feature = "low-power")] 44 #[cfg(feature = "low-power")]
45 crate::low_power::on_wakeup_irq(); 45 crate::low_power::on_wakeup_irq();
46 46
47 #[cfg(not(any(exti_c0, exti_g0, exti_l5, exti_u5, exti_h5, exti_h50)))] 47 #[cfg(not(any(exti_c0, exti_g0, exti_u0, exti_l5, exti_u5, exti_h5, exti_h50)))]
48 let bits = EXTI.pr(0).read().0; 48 let bits = EXTI.pr(0).read().0;
49 #[cfg(any(exti_c0, exti_g0, exti_l5, exti_u5, exti_h5, exti_h50))] 49 #[cfg(any(exti_c0, exti_g0, exti_u0, exti_l5, exti_u5, exti_h5, exti_h50))]
50 let bits = EXTI.rpr(0).read().0 | EXTI.fpr(0).read().0; 50 let bits = EXTI.rpr(0).read().0 | EXTI.fpr(0).read().0;
51 51
52 // We don't handle or change any EXTI lines above 16. 52 // We don't handle or change any EXTI lines above 16.
@@ -61,9 +61,9 @@ unsafe fn on_irq() {
61 } 61 }
62 62
63 // Clear pending 63 // Clear pending
64 #[cfg(not(any(exti_c0, exti_g0, exti_l5, exti_u5, exti_h5, exti_h50)))] 64 #[cfg(not(any(exti_c0, exti_g0, exti_u0, exti_l5, exti_u5, exti_h5, exti_h50)))]
65 EXTI.pr(0).write_value(Lines(bits)); 65 EXTI.pr(0).write_value(Lines(bits));
66 #[cfg(any(exti_c0, exti_g0, exti_l5, exti_u5, exti_h5, exti_h50))] 66 #[cfg(any(exti_c0, exti_g0, exti_u0, exti_l5, exti_u5, exti_h5, exti_h50))]
67 { 67 {
68 EXTI.rpr(0).write_value(Lines(bits)); 68 EXTI.rpr(0).write_value(Lines(bits));
69 EXTI.fpr(0).write_value(Lines(bits)); 69 EXTI.fpr(0).write_value(Lines(bits));
@@ -241,9 +241,9 @@ impl<'a> ExtiInputFuture<'a> {
241 EXTI.ftsr(0).modify(|w| w.set_line(pin, falling)); 241 EXTI.ftsr(0).modify(|w| w.set_line(pin, falling));
242 242
243 // clear pending bit 243 // clear pending bit
244 #[cfg(not(any(exti_c0, exti_g0, exti_l5, exti_u5, exti_h5, exti_h50)))] 244 #[cfg(not(any(exti_c0, exti_g0, exti_u0, exti_l5, exti_u5, exti_h5, exti_h50)))]
245 EXTI.pr(0).write(|w| w.set_line(pin, true)); 245 EXTI.pr(0).write(|w| w.set_line(pin, true));
246 #[cfg(any(exti_c0, exti_g0, exti_l5, exti_u5, exti_h5, exti_h50))] 246 #[cfg(any(exti_c0, exti_g0, exti_u0, exti_l5, exti_u5, exti_h5, exti_h50))]
247 { 247 {
248 EXTI.rpr(0).write(|w| w.set_line(pin, true)); 248 EXTI.rpr(0).write(|w| w.set_line(pin, true));
249 EXTI.fpr(0).write(|w| w.set_line(pin, true)); 249 EXTI.fpr(0).write(|w| w.set_line(pin, true));
diff --git a/embassy-stm32/src/flash/f4.rs b/embassy-stm32/src/flash/f4.rs
index 00e61f2d2..90f13ff29 100644
--- a/embassy-stm32/src/flash/f4.rs
+++ b/embassy-stm32/src/flash/f4.rs
@@ -16,7 +16,7 @@ mod alt_regions {
16 use embassy_hal_internal::PeripheralRef; 16 use embassy_hal_internal::PeripheralRef;
17 use stm32_metapac::FLASH_SIZE; 17 use stm32_metapac::FLASH_SIZE;
18 18
19 use crate::_generated::flash_regions::{OTPRegion, BANK1_REGION1, BANK1_REGION2, BANK1_REGION3, OTP_REGION}; 19 use crate::_generated::flash_regions::{BANK1_REGION1, BANK1_REGION2, BANK1_REGION3};
20 use crate::flash::{asynch, Async, Bank1Region1, Bank1Region2, Blocking, Error, Flash, FlashBank, FlashRegion}; 20 use crate::flash::{asynch, Async, Bank1Region1, Bank1Region2, Blocking, Error, Flash, FlashBank, FlashRegion};
21 use crate::peripherals::FLASH; 21 use crate::peripherals::FLASH;
22 22
@@ -62,7 +62,6 @@ mod alt_regions {
62 pub bank2_region1: AltBank2Region1<'d, MODE>, 62 pub bank2_region1: AltBank2Region1<'d, MODE>,
63 pub bank2_region2: AltBank2Region2<'d, MODE>, 63 pub bank2_region2: AltBank2Region2<'d, MODE>,
64 pub bank2_region3: AltBank2Region3<'d, MODE>, 64 pub bank2_region3: AltBank2Region3<'d, MODE>,
65 pub otp_region: OTPRegion<'d, MODE>,
66 } 65 }
67 66
68 impl<'d> Flash<'d> { 67 impl<'d> Flash<'d> {
@@ -79,7 +78,6 @@ mod alt_regions {
79 bank2_region1: AltBank2Region1(&ALT_BANK2_REGION1, unsafe { p.clone_unchecked() }, PhantomData), 78 bank2_region1: AltBank2Region1(&ALT_BANK2_REGION1, unsafe { p.clone_unchecked() }, PhantomData),
80 bank2_region2: AltBank2Region2(&ALT_BANK2_REGION2, unsafe { p.clone_unchecked() }, PhantomData), 79 bank2_region2: AltBank2Region2(&ALT_BANK2_REGION2, unsafe { p.clone_unchecked() }, PhantomData),
81 bank2_region3: AltBank2Region3(&ALT_BANK2_REGION3, unsafe { p.clone_unchecked() }, PhantomData), 80 bank2_region3: AltBank2Region3(&ALT_BANK2_REGION3, unsafe { p.clone_unchecked() }, PhantomData),
82 otp_region: OTPRegion(&OTP_REGION, unsafe { p.clone_unchecked() }, PhantomData),
83 } 81 }
84 } 82 }
85 83
@@ -96,7 +94,6 @@ mod alt_regions {
96 bank2_region1: AltBank2Region1(&ALT_BANK2_REGION1, unsafe { p.clone_unchecked() }, PhantomData), 94 bank2_region1: AltBank2Region1(&ALT_BANK2_REGION1, unsafe { p.clone_unchecked() }, PhantomData),
97 bank2_region2: AltBank2Region2(&ALT_BANK2_REGION2, unsafe { p.clone_unchecked() }, PhantomData), 95 bank2_region2: AltBank2Region2(&ALT_BANK2_REGION2, unsafe { p.clone_unchecked() }, PhantomData),
98 bank2_region3: AltBank2Region3(&ALT_BANK2_REGION3, unsafe { p.clone_unchecked() }, PhantomData), 96 bank2_region3: AltBank2Region3(&ALT_BANK2_REGION3, unsafe { p.clone_unchecked() }, PhantomData),
99 otp_region: OTPRegion(&OTP_REGION, unsafe { p.clone_unchecked() }, PhantomData),
100 } 97 }
101 } 98 }
102 } 99 }
diff --git a/embassy-stm32/src/flash/h50.rs b/embassy-stm32/src/flash/h50.rs
index db05bef5d..5b15be261 100644
--- a/embassy-stm32/src/flash/h50.rs
+++ b/embassy-stm32/src/flash/h50.rs
@@ -55,7 +55,6 @@ pub(crate) unsafe fn blocking_write(start_address: u32, buf: &[u8; WRITE_SIZE])
55} 55}
56 56
57pub(crate) unsafe fn blocking_erase_sector(sector: &FlashSector) -> Result<(), Error> { 57pub(crate) unsafe fn blocking_erase_sector(sector: &FlashSector) -> Result<(), Error> {
58 assert!(sector.bank != FlashBank::Otp);
59 assert!(sector.index_in_bank < 8); 58 assert!(sector.index_in_bank < 8);
60 59
61 while busy() {} 60 while busy() {}
@@ -63,9 +62,8 @@ pub(crate) unsafe fn blocking_erase_sector(sector: &FlashSector) -> Result<(), E
63 interrupt::free(|_| { 62 interrupt::free(|_| {
64 pac::FLASH.nscr().modify(|w| { 63 pac::FLASH.nscr().modify(|w| {
65 w.set_bksel(match sector.bank { 64 w.set_bksel(match sector.bank {
66 FlashBank::Bank1 => Bksel::B_0X0, 65 FlashBank::Bank1 => Bksel::BANK1,
67 FlashBank::Bank2 => Bksel::B_0X1, 66 FlashBank::Bank2 => Bksel::BANK2,
68 _ => unreachable!(),
69 }); 67 });
70 w.set_snb(sector.index_in_bank); 68 w.set_snb(sector.index_in_bank);
71 w.set_ser(true); 69 w.set_ser(true);
diff --git a/embassy-stm32/src/flash/mod.rs b/embassy-stm32/src/flash/mod.rs
index 1d8031e82..9d7861816 100644
--- a/embassy-stm32/src/flash/mod.rs
+++ b/embassy-stm32/src/flash/mod.rs
@@ -89,8 +89,6 @@ pub enum FlashBank {
89 Bank1 = 0, 89 Bank1 = 0,
90 /// Bank 2 90 /// Bank 2
91 Bank2 = 1, 91 Bank2 = 1,
92 /// OTP region
93 Otp,
94} 92}
95 93
96#[cfg_attr(any(flash_l0, flash_l1, flash_l4, flash_wl, flash_wb), path = "l.rs")] 94#[cfg_attr(any(flash_l0, flash_l1, flash_l4, flash_wl, flash_wb), path = "l.rs")]
diff --git a/embassy-stm32/src/rcc/l.rs b/embassy-stm32/src/rcc/l.rs
index 9079ddd41..d7235ac7f 100644
--- a/embassy-stm32/src/rcc/l.rs
+++ b/embassy-stm32/src/rcc/l.rs
@@ -49,6 +49,7 @@ pub struct Config {
49 pub sys: Sysclk, 49 pub sys: Sysclk,
50 pub ahb_pre: AHBPrescaler, 50 pub ahb_pre: AHBPrescaler,
51 pub apb1_pre: APBPrescaler, 51 pub apb1_pre: APBPrescaler,
52 #[cfg(not(stm32u0))]
52 pub apb2_pre: APBPrescaler, 53 pub apb2_pre: APBPrescaler,
53 #[cfg(any(stm32wl5x, stm32wb))] 54 #[cfg(any(stm32wl5x, stm32wb))]
54 pub core2_ahb_pre: AHBPrescaler, 55 pub core2_ahb_pre: AHBPrescaler,
@@ -75,6 +76,7 @@ impl Default for Config {
75 sys: Sysclk::MSI, 76 sys: Sysclk::MSI,
76 ahb_pre: AHBPrescaler::DIV1, 77 ahb_pre: AHBPrescaler::DIV1,
77 apb1_pre: APBPrescaler::DIV1, 78 apb1_pre: APBPrescaler::DIV1,
79 #[cfg(not(stm32u0))]
78 apb2_pre: APBPrescaler::DIV1, 80 apb2_pre: APBPrescaler::DIV1,
79 #[cfg(any(stm32wl5x, stm32wb))] 81 #[cfg(any(stm32wl5x, stm32wb))]
80 core2_ahb_pre: AHBPrescaler::DIV1, 82 core2_ahb_pre: AHBPrescaler::DIV1,
@@ -130,7 +132,7 @@ pub const WPAN_DEFAULT: Config = Config {
130}; 132};
131 133
132fn msi_enable(range: MSIRange) { 134fn msi_enable(range: MSIRange) {
133 #[cfg(any(stm32l4, stm32l5, stm32wb, stm32wl))] 135 #[cfg(any(stm32l4, stm32l5, stm32wb, stm32wl, stm32u0))]
134 RCC.cr().modify(|w| { 136 RCC.cr().modify(|w| {
135 #[cfg(not(stm32wb))] 137 #[cfg(not(stm32wb))]
136 w.set_msirgsel(crate::pac::rcc::vals::Msirgsel::CR); 138 w.set_msirgsel(crate::pac::rcc::vals::Msirgsel::CR);
@@ -240,7 +242,7 @@ pub(crate) unsafe fn init(config: Config) {
240 let pll_input = PllInput { 242 let pll_input = PllInput {
241 hse, 243 hse,
242 hsi, 244 hsi,
243 #[cfg(any(stm32l4, stm32l5, stm32wb, stm32wl))] 245 #[cfg(any(stm32l4, stm32l5, stm32wb, stm32wl, stm32u0))]
244 msi, 246 msi,
245 }; 247 };
246 let pll = init_pll(PllInstance::Pll, config.pll, &pll_input); 248 let pll = init_pll(PllInstance::Pll, config.pll, &pll_input);
@@ -254,6 +256,10 @@ pub(crate) unsafe fn init(config: Config) {
254 Sysclk::HSI => hsi.unwrap(), 256 Sysclk::HSI => hsi.unwrap(),
255 Sysclk::MSI => msi.unwrap(), 257 Sysclk::MSI => msi.unwrap(),
256 Sysclk::PLL1_R => pll.r.unwrap(), 258 Sysclk::PLL1_R => pll.r.unwrap(),
259 #[cfg(stm32u0)]
260 Sysclk::LSI | Sysclk::LSE => todo!(),
261 #[cfg(stm32u0)]
262 Sysclk::_RESERVED_6 | Sysclk::_RESERVED_7 => unreachable!(),
257 }; 263 };
258 264
259 #[cfg(rcc_l4plus)] 265 #[cfg(rcc_l4plus)]
@@ -263,6 +269,7 @@ pub(crate) unsafe fn init(config: Config) {
263 269
264 let hclk1 = sys_clk / config.ahb_pre; 270 let hclk1 = sys_clk / config.ahb_pre;
265 let (pclk1, pclk1_tim) = super::util::calc_pclk(hclk1, config.apb1_pre); 271 let (pclk1, pclk1_tim) = super::util::calc_pclk(hclk1, config.apb1_pre);
272 #[cfg(not(stm32u0))]
266 let (pclk2, pclk2_tim) = super::util::calc_pclk(hclk1, config.apb2_pre); 273 let (pclk2, pclk2_tim) = super::util::calc_pclk(hclk1, config.apb2_pre);
267 #[cfg(any(stm32l4, stm32l5, stm32wlex))] 274 #[cfg(any(stm32l4, stm32l5, stm32wlex))]
268 let hclk2 = hclk1; 275 let hclk2 = hclk1;
@@ -315,6 +322,13 @@ pub(crate) unsafe fn init(config: Config) {
315 ..=64_000_000 => 3, 322 ..=64_000_000 => 3,
316 _ => 4, 323 _ => 4,
317 }; 324 };
325 #[cfg(stm32u0)]
326 let latency = match hclk1.0 {
327 // VOS RANGE1, others TODO.
328 ..=24_000_000 => 0,
329 ..=48_000_000 => 1,
330 _ => 2,
331 };
318 332
319 #[cfg(stm32l1)] 333 #[cfg(stm32l1)]
320 FLASH.acr().write(|w| w.set_acc64(true)); 334 FLASH.acr().write(|w| w.set_acc64(true));
@@ -326,7 +340,11 @@ pub(crate) unsafe fn init(config: Config) {
326 RCC.cfgr().modify(|w| { 340 RCC.cfgr().modify(|w| {
327 w.set_sw(config.sys); 341 w.set_sw(config.sys);
328 w.set_hpre(config.ahb_pre); 342 w.set_hpre(config.ahb_pre);
343 #[cfg(stm32u0)]
344 w.set_ppre(config.apb1_pre);
345 #[cfg(not(stm32u0))]
329 w.set_ppre1(config.apb1_pre); 346 w.set_ppre1(config.apb1_pre);
347 #[cfg(not(stm32u0))]
330 w.set_ppre2(config.apb2_pre); 348 w.set_ppre2(config.apb2_pre);
331 }); 349 });
332 while RCC.cfgr().read().sws() != config.sys {} 350 while RCC.cfgr().read().sws() != config.sys {}
@@ -353,8 +371,10 @@ pub(crate) unsafe fn init(config: Config) {
353 #[cfg(any(stm32l4, stm32l5, stm32wb, stm32wl))] 371 #[cfg(any(stm32l4, stm32l5, stm32wb, stm32wl))]
354 hclk3: Some(hclk3), 372 hclk3: Some(hclk3),
355 pclk1: Some(pclk1), 373 pclk1: Some(pclk1),
374 #[cfg(not(stm32u0))]
356 pclk2: Some(pclk2), 375 pclk2: Some(pclk2),
357 pclk1_tim: Some(pclk1_tim), 376 pclk1_tim: Some(pclk1_tim),
377 #[cfg(not(stm32u0))]
358 pclk2_tim: Some(pclk2_tim), 378 pclk2_tim: Some(pclk2_tim),
359 #[cfg(stm32wl)] 379 #[cfg(stm32wl)]
360 pclk3: Some(hclk3), 380 pclk3: Some(hclk3),
@@ -408,7 +428,7 @@ fn msirange_to_hertz(range: MSIRange) -> Hertz {
408 Hertz(32_768 * (1 << (range as u8 + 1))) 428 Hertz(32_768 * (1 << (range as u8 + 1)))
409} 429}
410 430
411#[cfg(any(stm32l4, stm32l5, stm32wb, stm32wl))] 431#[cfg(any(stm32l4, stm32l5, stm32wb, stm32wl, stm32u0))]
412fn msirange_to_hertz(range: MSIRange) -> Hertz { 432fn msirange_to_hertz(range: MSIRange) -> Hertz {
413 match range { 433 match range {
414 MSIRange::RANGE100K => Hertz(100_000), 434 MSIRange::RANGE100K => Hertz(100_000),
@@ -521,7 +541,7 @@ mod pll {
521 } 541 }
522} 542}
523 543
524#[cfg(any(stm32l4, stm32l5, stm32wb, stm32wl))] 544#[cfg(any(stm32l4, stm32l5, stm32wb, stm32wl, stm32u0))]
525mod pll { 545mod pll {
526 use super::{pll_enable, PllInstance}; 546 use super::{pll_enable, PllInstance};
527 pub use crate::pac::rcc::vals::{ 547 pub use crate::pac::rcc::vals::{
diff --git a/embassy-stm32/src/rcc/mco.rs b/embassy-stm32/src/rcc/mco.rs
index d8604e07e..4b22a099d 100644
--- a/embassy-stm32/src/rcc/mco.rs
+++ b/embassy-stm32/src/rcc/mco.rs
@@ -52,7 +52,7 @@ macro_rules! impl_peri {
52 }; 52 };
53} 53}
54 54
55#[cfg(any(rcc_c0, rcc_g0))] 55#[cfg(any(rcc_c0, rcc_g0, rcc_u0))]
56#[allow(unused_imports)] 56#[allow(unused_imports)]
57use self::{McoSource as Mco1Source, McoSource as Mco2Source}; 57use self::{McoSource as Mco1Source, McoSource as Mco2Source};
58 58
diff --git a/embassy-stm32/src/rcc/mod.rs b/embassy-stm32/src/rcc/mod.rs
index d53d02203..a4e497fe7 100644
--- a/embassy-stm32/src/rcc/mod.rs
+++ b/embassy-stm32/src/rcc/mod.rs
@@ -25,7 +25,7 @@ pub use hsi48::*;
25#[cfg_attr(stm32g0, path = "g0.rs")] 25#[cfg_attr(stm32g0, path = "g0.rs")]
26#[cfg_attr(stm32g4, path = "g4.rs")] 26#[cfg_attr(stm32g4, path = "g4.rs")]
27#[cfg_attr(any(stm32h5, stm32h7), path = "h.rs")] 27#[cfg_attr(any(stm32h5, stm32h7), path = "h.rs")]
28#[cfg_attr(any(stm32l0, stm32l1, stm32l4, stm32l5, stm32wb, stm32wl), path = "l.rs")] 28#[cfg_attr(any(stm32l0, stm32l1, stm32l4, stm32l5, stm32wb, stm32wl, stm32u0), path = "l.rs")]
29#[cfg_attr(stm32u5, path = "u5.rs")] 29#[cfg_attr(stm32u5, path = "u5.rs")]
30#[cfg_attr(stm32wba, path = "wba.rs")] 30#[cfg_attr(stm32wba, path = "wba.rs")]
31mod _version; 31mod _version;
@@ -111,7 +111,7 @@ mod util {
111 } 111 }
112} 112}
113 113
114/// Get the kernel clocok frequency of the peripheral `T`. 114/// Get the kernel clock frequency of the peripheral `T`.
115/// 115///
116/// # Panics 116/// # Panics
117/// 117///
@@ -119,3 +119,21 @@ mod util {
119pub fn frequency<T: RccPeripheral>() -> Hertz { 119pub fn frequency<T: RccPeripheral>() -> Hertz {
120 T::frequency() 120 T::frequency()
121} 121}
122
123/// Enables and resets peripheral `T`.
124///
125/// # Safety
126///
127/// Peripheral must not be in use.
128pub unsafe fn enable_and_reset<T: RccPeripheral>() {
129 T::enable_and_reset();
130}
131
132/// Disables peripheral `T`.
133///
134/// # Safety
135///
136/// Peripheral must not be in use.
137pub unsafe fn disable<T: RccPeripheral>() {
138 T::disable();
139}
diff --git a/embassy-stm32/src/spi/mod.rs b/embassy-stm32/src/spi/mod.rs
index 0b38c4288..450975f18 100644
--- a/embassy-stm32/src/spi/mod.rs
+++ b/embassy-stm32/src/spi/mod.rs
@@ -735,18 +735,22 @@ trait RegsExt {
735 735
736impl RegsExt for Regs { 736impl RegsExt for Regs {
737 fn tx_ptr<W>(&self) -> *mut W { 737 fn tx_ptr<W>(&self) -> *mut W {
738 #[cfg(not(any(spi_v3, spi_v4, spi_v5)))] 738 #[cfg(any(spi_v1, spi_f1))]
739 let dr = self.dr(); 739 let dr = self.dr();
740 #[cfg(spi_v2)]
741 let dr = self.dr16();
740 #[cfg(any(spi_v3, spi_v4, spi_v5))] 742 #[cfg(any(spi_v3, spi_v4, spi_v5))]
741 let dr = self.txdr(); 743 let dr = self.txdr32();
742 dr.as_ptr() as *mut W 744 dr.as_ptr() as *mut W
743 } 745 }
744 746
745 fn rx_ptr<W>(&self) -> *mut W { 747 fn rx_ptr<W>(&self) -> *mut W {
746 #[cfg(not(any(spi_v3, spi_v4, spi_v5)))] 748 #[cfg(any(spi_v1, spi_f1))]
747 let dr = self.dr(); 749 let dr = self.dr();
750 #[cfg(spi_v2)]
751 let dr = self.dr16();
748 #[cfg(any(spi_v3, spi_v4, spi_v5))] 752 #[cfg(any(spi_v3, spi_v4, spi_v5))]
749 let dr = self.rxdr(); 753 let dr = self.rxdr32();
750 dr.as_ptr() as *mut W 754 dr.as_ptr() as *mut W
751 } 755 }
752} 756}
@@ -815,11 +819,14 @@ fn spin_until_rx_ready(regs: Regs) -> Result<(), Error> {
815fn flush_rx_fifo(regs: Regs) { 819fn flush_rx_fifo(regs: Regs) {
816 #[cfg(not(any(spi_v3, spi_v4, spi_v5)))] 820 #[cfg(not(any(spi_v3, spi_v4, spi_v5)))]
817 while regs.sr().read().rxne() { 821 while regs.sr().read().rxne() {
822 #[cfg(not(spi_v2))]
818 let _ = regs.dr().read(); 823 let _ = regs.dr().read();
824 #[cfg(spi_v2)]
825 let _ = regs.dr16().read();
819 } 826 }
820 #[cfg(any(spi_v3, spi_v4, spi_v5))] 827 #[cfg(any(spi_v3, spi_v4, spi_v5))]
821 while regs.sr().read().rxp() { 828 while regs.sr().read().rxp() {
822 let _ = regs.rxdr().read(); 829 let _ = regs.rxdr32().read();
823 } 830 }
824} 831}
825 832
diff --git a/embassy-stm32/src/usb/otg.rs b/embassy-stm32/src/usb/otg.rs
index b0e7067bd..cabc06367 100644
--- a/embassy-stm32/src/usb/otg.rs
+++ b/embassy-stm32/src/usb/otg.rs
@@ -317,7 +317,7 @@ impl<'d, T: Instance> Driver<'d, T> {
317 /// 317 ///
318 /// # Arguments 318 /// # Arguments
319 /// 319 ///
320 /// * `ep_out_buffer` - An internal buffer used to temporarily store recevied packets. 320 /// * `ep_out_buffer` - An internal buffer used to temporarily store received packets.
321 /// Must be large enough to fit all OUT endpoint max packet sizes. 321 /// Must be large enough to fit all OUT endpoint max packet sizes.
322 /// Endpoint allocation will fail if it is too small. 322 /// Endpoint allocation will fail if it is too small.
323 pub fn new_fs( 323 pub fn new_fs(
@@ -348,7 +348,7 @@ impl<'d, T: Instance> Driver<'d, T> {
348 /// 348 ///
349 /// # Arguments 349 /// # Arguments
350 /// 350 ///
351 /// * `ep_out_buffer` - An internal buffer used to temporarily store recevied packets. 351 /// * `ep_out_buffer` - An internal buffer used to temporarily store received packets.
352 /// Must be large enough to fit all OUT endpoint max packet sizes. 352 /// Must be large enough to fit all OUT endpoint max packet sizes.
353 /// Endpoint allocation will fail if it is too small. 353 /// Endpoint allocation will fail if it is too small.
354 pub fn new_hs_ulpi( 354 pub fn new_hs_ulpi(
@@ -562,51 +562,29 @@ impl<'d, T: Instance> Bus<'d, T> {
562 fn init(&mut self) { 562 fn init(&mut self) {
563 super::common_init::<T>(); 563 super::common_init::<T>();
564 564
565 #[cfg(stm32f7)] 565 // Enable ULPI clock if external PHY is used
566 { 566 let _ulpien = !self.phy_type.internal();
567 // Enable ULPI clock if external PHY is used
568 let ulpien = !self.phy_type.internal();
569 critical_section::with(|_| {
570 crate::pac::RCC.ahb1enr().modify(|w| {
571 if T::HIGH_SPEED {
572 w.set_usb_otg_hsulpien(ulpien);
573 } else {
574 w.set_usb_otg_hsen(ulpien);
575 }
576 });
577 567
578 // Low power mode 568 #[cfg(any(stm32f2, stm32f4, stm32f7))]
579 crate::pac::RCC.ahb1lpenr().modify(|w| { 569 if T::HIGH_SPEED {
580 if T::HIGH_SPEED { 570 critical_section::with(|_| {
581 w.set_usb_otg_hsulpilpen(ulpien); 571 let rcc = crate::pac::RCC;
582 } else { 572 rcc.ahb1enr().modify(|w| w.set_usb_otg_hsulpien(_ulpien));
583 w.set_usb_otg_hslpen(ulpien); 573 rcc.ahb1lpenr().modify(|w| w.set_usb_otg_hsulpilpen(_ulpien));
584 }
585 });
586 }); 574 });
587 } 575 }
588 576
589 #[cfg(stm32h7)] 577 #[cfg(stm32h7)]
590 { 578 critical_section::with(|_| {
591 // Enable ULPI clock if external PHY is used 579 let rcc = crate::pac::RCC;
592 let ulpien = !self.phy_type.internal(); 580 if T::HIGH_SPEED {
593 critical_section::with(|_| { 581 rcc.ahb1enr().modify(|w| w.set_usb_otg_hs_ulpien(_ulpien));
594 crate::pac::RCC.ahb1enr().modify(|w| { 582 rcc.ahb1lpenr().modify(|w| w.set_usb_otg_hs_ulpilpen(_ulpien));
595 if T::HIGH_SPEED { 583 } else {
596 w.set_usb_otg_hs_ulpien(ulpien); 584 rcc.ahb1enr().modify(|w| w.set_usb_otg_fs_ulpien(_ulpien));
597 } else { 585 rcc.ahb1lpenr().modify(|w| w.set_usb_otg_fs_ulpilpen(_ulpien));
598 w.set_usb_otg_fs_ulpien(ulpien); 586 }
599 } 587 });
600 });
601 crate::pac::RCC.ahb1lpenr().modify(|w| {
602 if T::HIGH_SPEED {
603 w.set_usb_otg_hs_ulpilpen(ulpien);
604 } else {
605 w.set_usb_otg_fs_ulpilpen(ulpien);
606 }
607 });
608 });
609 }
610 588
611 let r = T::regs(); 589 let r = T::regs();
612 let core_id = r.cid().read().0; 590 let core_id = r.cid().read().0;
diff --git a/embassy-sync/CHANGELOG.md b/embassy-sync/CHANGELOG.md
index e7db97ef7..3f6b39d8b 100644
--- a/embassy-sync/CHANGELOG.md
+++ b/embassy-sync/CHANGELOG.md
@@ -5,6 +5,10 @@ All notable changes to this project will be documented in this file.
5The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 5The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 6and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7 7
8## Unreleased
9
10- Add `len`, `is_empty` and `is_full` functions to `Channel`.
11
8## 0.5.0 - 2023-12-04 12## 0.5.0 - 2023-12-04
9 13
10- Add a PriorityChannel. 14- Add a PriorityChannel.
@@ -35,7 +39,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
35- Remove unnecessary uses of `atomic-polyfill` 39- Remove unnecessary uses of `atomic-polyfill`
36- Add `#[must_use]` to all futures. 40- Add `#[must_use]` to all futures.
37 41
38
39## 0.1.0 - 2022-08-26 42## 0.1.0 - 2022-08-26
40 43
41- First release 44- First release
diff --git a/embassy-sync/src/channel.rs b/embassy-sync/src/channel.rs
index 48f4dafd6..18be462cb 100644
--- a/embassy-sync/src/channel.rs
+++ b/embassy-sync/src/channel.rs
@@ -449,6 +449,18 @@ impl<T, const N: usize> ChannelState<T, N> {
449 Poll::Pending 449 Poll::Pending
450 } 450 }
451 } 451 }
452
453 fn len(&self) -> usize {
454 self.queue.len()
455 }
456
457 fn is_empty(&self) -> bool {
458 self.queue.is_empty()
459 }
460
461 fn is_full(&self) -> bool {
462 self.queue.is_full()
463 }
452} 464}
453 465
454/// A bounded channel for communicating between asynchronous tasks 466/// A bounded channel for communicating between asynchronous tasks
@@ -572,6 +584,21 @@ where
572 pub fn try_receive(&self) -> Result<T, TryReceiveError> { 584 pub fn try_receive(&self) -> Result<T, TryReceiveError> {
573 self.lock(|c| c.try_receive()) 585 self.lock(|c| c.try_receive())
574 } 586 }
587
588 /// Returns the number of elements currently in the channel.
589 pub fn len(&self) -> usize {
590 self.lock(|c| c.len())
591 }
592
593 /// Returns whether the channel is empty.
594 pub fn is_empty(&self) -> bool {
595 self.lock(|c| c.is_empty())
596 }
597
598 /// Returns whether the channel is full.
599 pub fn is_full(&self) -> bool {
600 self.lock(|c| c.is_full())
601 }
575} 602}
576 603
577/// Implements the DynamicChannel to allow creating types that are unaware of the queue size with the 604/// Implements the DynamicChannel to allow creating types that are unaware of the queue size with the
diff --git a/embassy-sync/src/mutex.rs b/embassy-sync/src/mutex.rs
index 72459d660..b48a408c4 100644
--- a/embassy-sync/src/mutex.rs
+++ b/embassy-sync/src/mutex.rs
@@ -3,6 +3,7 @@
3//! This module provides a mutex that can be used to synchronize data between asynchronous tasks. 3//! This module provides a mutex that can be used to synchronize data between asynchronous tasks.
4use core::cell::{RefCell, UnsafeCell}; 4use core::cell::{RefCell, UnsafeCell};
5use core::future::poll_fn; 5use core::future::poll_fn;
6use core::mem;
6use core::ops::{Deref, DerefMut}; 7use core::ops::{Deref, DerefMut};
7use core::task::Poll; 8use core::task::Poll;
8 9
@@ -134,6 +135,7 @@ where
134/// successfully locked the mutex, and grants access to the contents. 135/// successfully locked the mutex, and grants access to the contents.
135/// 136///
136/// Dropping it unlocks the mutex. 137/// Dropping it unlocks the mutex.
138#[clippy::has_significant_drop]
137pub struct MutexGuard<'a, M, T> 139pub struct MutexGuard<'a, M, T>
138where 140where
139 M: RawMutex, 141 M: RawMutex,
@@ -142,6 +144,25 @@ where
142 mutex: &'a Mutex<M, T>, 144 mutex: &'a Mutex<M, T>,
143} 145}
144 146
147impl<'a, M, T> MutexGuard<'a, M, T>
148where
149 M: RawMutex,
150 T: ?Sized,
151{
152 /// Returns a locked view over a portion of the locked data.
153 pub fn map<U>(this: Self, fun: impl FnOnce(&mut T) -> &mut U) -> MappedMutexGuard<'a, M, U> {
154 let mutex = this.mutex;
155 let value = fun(unsafe { &mut *this.mutex.inner.get() });
156 // Don't run the `drop` method for MutexGuard. The ownership of the underlying
157 // locked state is being moved to the returned MappedMutexGuard.
158 mem::forget(this);
159 MappedMutexGuard {
160 state: &mutex.state,
161 value,
162 }
163 }
164}
165
145impl<'a, M, T> Drop for MutexGuard<'a, M, T> 166impl<'a, M, T> Drop for MutexGuard<'a, M, T>
146where 167where
147 M: RawMutex, 168 M: RawMutex,
@@ -180,3 +201,115 @@ where
180 unsafe { &mut *(self.mutex.inner.get()) } 201 unsafe { &mut *(self.mutex.inner.get()) }
181 } 202 }
182} 203}
204
205/// A handle to a held `Mutex` that has had a function applied to it via [`MutexGuard::map`] or
206/// [`MappedMutexGuard::map`].
207///
208/// This can be used to hold a subfield of the protected data.
209#[clippy::has_significant_drop]
210pub struct MappedMutexGuard<'a, M, T>
211where
212 M: RawMutex,
213 T: ?Sized,
214{
215 state: &'a BlockingMutex<M, RefCell<State>>,
216 value: *mut T,
217}
218
219impl<'a, M, T> MappedMutexGuard<'a, M, T>
220where
221 M: RawMutex,
222 T: ?Sized,
223{
224 /// Returns a locked view over a portion of the locked data.
225 pub fn map<U>(this: Self, fun: impl FnOnce(&mut T) -> &mut U) -> MappedMutexGuard<'a, M, U> {
226 let state = this.state;
227 let value = fun(unsafe { &mut *this.value });
228 // Don't run the `drop` method for MutexGuard. The ownership of the underlying
229 // locked state is being moved to the returned MappedMutexGuard.
230 mem::forget(this);
231 MappedMutexGuard { state, value }
232 }
233}
234
235impl<'a, M, T> Deref for MappedMutexGuard<'a, M, T>
236where
237 M: RawMutex,
238 T: ?Sized,
239{
240 type Target = T;
241 fn deref(&self) -> &Self::Target {
242 // Safety: the MutexGuard represents exclusive access to the contents
243 // of the mutex, so it's OK to get it.
244 unsafe { &*self.value }
245 }
246}
247
248impl<'a, M, T> DerefMut for MappedMutexGuard<'a, M, T>
249where
250 M: RawMutex,
251 T: ?Sized,
252{
253 fn deref_mut(&mut self) -> &mut Self::Target {
254 // Safety: the MutexGuard represents exclusive access to the contents
255 // of the mutex, so it's OK to get it.
256 unsafe { &mut *self.value }
257 }
258}
259
260impl<'a, M, T> Drop for MappedMutexGuard<'a, M, T>
261where
262 M: RawMutex,
263 T: ?Sized,
264{
265 fn drop(&mut self) {
266 self.state.lock(|s| {
267 let mut s = unwrap!(s.try_borrow_mut());
268 s.locked = false;
269 s.waker.wake();
270 })
271 }
272}
273
274unsafe impl<M, T> Send for MappedMutexGuard<'_, M, T>
275where
276 M: RawMutex + Sync,
277 T: Send + ?Sized,
278{
279}
280
281unsafe impl<M, T> Sync for MappedMutexGuard<'_, M, T>
282where
283 M: RawMutex + Sync,
284 T: Sync + ?Sized,
285{
286}
287
288#[cfg(test)]
289mod tests {
290 use crate::blocking_mutex::raw::NoopRawMutex;
291 use crate::mutex::{Mutex, MutexGuard};
292
293 #[futures_test::test]
294 async fn mapped_guard_releases_lock_when_dropped() {
295 let mutex: Mutex<NoopRawMutex, [i32; 2]> = Mutex::new([0, 1]);
296
297 {
298 let guard = mutex.lock().await;
299 assert_eq!(*guard, [0, 1]);
300 let mut mapped = MutexGuard::map(guard, |this| &mut this[1]);
301 assert_eq!(*mapped, 1);
302 *mapped = 2;
303 }
304
305 {
306 let guard = mutex.lock().await;
307 assert_eq!(*guard, [0, 2]);
308 let mut mapped = MutexGuard::map(guard, |this| &mut this[1]);
309 assert_eq!(*mapped, 2);
310 *mapped = 3;
311 }
312
313 assert_eq!(*mutex.lock().await, [0, 3]);
314 }
315}
diff --git a/embassy-time-queue-driver/README.md b/embassy-time-queue-driver/README.md
index 8852b0358..b9fb12d94 100644
--- a/embassy-time-queue-driver/README.md
+++ b/embassy-time-queue-driver/README.md
@@ -4,5 +4,5 @@ This crate contains the driver trait used by the [`embassy-time`](https://crates
4 4
5You should rarely need to use this crate directly. Only use it when implementing your own timer queue. 5You should rarely need to use this crate directly. Only use it when implementing your own timer queue.
6 6
7There is two timer queue implementations, one in `embassy-time` enabled by the `generic-queue` feature, and 7There is two timer queue implementations, one in `embassy-time` enabled by the `generic-queue` feature, and
8another in `embassy-executor` enabled by the `integrated-timers` feature. 8another in `embassy-executor` enabled by the `integrated-timers` feature.
diff --git a/embassy-time/README.md b/embassy-time/README.md
index f5d46df7b..6a4b049b4 100644
--- a/embassy-time/README.md
+++ b/embassy-time/README.md
@@ -5,7 +5,7 @@ Timekeeping, delays and timeouts.
5Timekeeping is done with elapsed time since system boot. Time is represented in 5Timekeeping is done with elapsed time since system boot. Time is represented in
6ticks, where the tick rate is defined either by the driver (in the case of a fixed-rate 6ticks, where the tick rate is defined either by the driver (in the case of a fixed-rate
7tick) or chosen by the user with a [tick rate](#tick-rate) feature. The chosen 7tick) or chosen by the user with a [tick rate](#tick-rate) feature. The chosen
8tick rate applies to everything in `embassy-time` and thus determines the maximum 8tick rate applies to everything in `embassy-time` and thus determines the maximum
9timing resolution of <code>(1 / tick_rate) seconds</code>. 9timing resolution of <code>(1 / tick_rate) seconds</code>.
10 10
11Tick counts are 64 bits. The default tick rate of 1Mhz supports 11Tick counts are 64 bits. The default tick rate of 1Mhz supports
diff --git a/embassy-usb/README.md b/embassy-usb/README.md
index d2adae4f5..400fc6695 100644
--- a/embassy-usb/README.md
+++ b/embassy-usb/README.md
@@ -34,8 +34,8 @@ They can be set in two ways:
34- Via Cargo features: enable a feature like `<name>-<value>`. `name` must be in lowercase and 34- Via Cargo features: enable a feature like `<name>-<value>`. `name` must be in lowercase and
35use dashes instead of underscores. For example. `max-interface-count-3`. Only a selection of values 35use dashes instead of underscores. For example. `max-interface-count-3`. Only a selection of values
36is available, check `Cargo.toml` for the list. 36is available, check `Cargo.toml` for the list.
37- Via environment variables at build time: set the variable named `EMBASSY_USB_<value>`. For example 37- Via environment variables at build time: set the variable named `EMBASSY_USB_<value>`. For example
38`EMBASSY_USB_MAX_INTERFACE_COUNT=3 cargo build`. You can also set them in the `[env]` section of `.cargo/config.toml`. 38`EMBASSY_USB_MAX_INTERFACE_COUNT=3 cargo build`. You can also set them in the `[env]` section of `.cargo/config.toml`.
39Any value can be set, unlike with Cargo features. 39Any value can be set, unlike with Cargo features.
40 40
41Environment variables take precedence over Cargo features. If two Cargo features are enabled for the same setting 41Environment variables take precedence over Cargo features. If two Cargo features are enabled for the same setting
diff --git a/embassy-usb/src/builder.rs b/embassy-usb/src/builder.rs
index c06107396..387b780de 100644
--- a/embassy-usb/src/builder.rs
+++ b/embassy-usb/src/builder.rs
@@ -38,11 +38,12 @@ pub struct Config<'a> {
38 38
39 /// Maximum packet size in bytes for the control endpoint 0. 39 /// Maximum packet size in bytes for the control endpoint 0.
40 /// 40 ///
41 /// Valid values are 8, 16, 32 and 64. There's generally no need to change this from the default 41 /// Valid values depend on the speed at which the bus is enumerated.
42 /// value of 8 bytes unless a class uses control transfers for sending large amounts of data, in 42 /// - low speed: 8
43 /// which case using a larger packet size may be more efficient. 43 /// - full speed: 8, 16, 32, or 64
44 /// - high speed: 64
44 /// 45 ///
45 /// Default: 8 bytes 46 /// Default: 64 bytes
46 pub max_packet_size_0: u8, 47 pub max_packet_size_0: u8,
47 48
48 /// Manufacturer name string descriptor. 49 /// Manufacturer name string descriptor.
diff --git a/examples/boot/bootloader/stm32-dual-bank/README.md b/examples/boot/bootloader/stm32-dual-bank/README.md
index 3de3171cd..cd6c0bc84 100644
--- a/examples/boot/bootloader/stm32-dual-bank/README.md
+++ b/examples/boot/bootloader/stm32-dual-bank/README.md
@@ -2,16 +2,16 @@
2 2
3## Overview 3## Overview
4 4
5This bootloader leverages `embassy-boot` to interact with the flash. 5This bootloader leverages `embassy-boot` to interact with the flash.
6This example targets STM32 devices with dual-bank flash memory, with a primary focus on the STM32H747XI series. 6This example targets STM32 devices with dual-bank flash memory, with a primary focus on the STM32H747XI series.
7Users must modify the `memory.x` configuration file to match with the memory layout of their specific STM32 device. 7Users must modify the `memory.x` configuration file to match with the memory layout of their specific STM32 device.
8 8
9Additionally, this example can be extended to utilize external flash memory, such as QSPI, for storing partitions. 9Additionally, this example can be extended to utilize external flash memory, such as QSPI, for storing partitions.
10 10
11## Memory Configuration 11## Memory Configuration
12 12
13In this example's `memory.x` file, various symbols are defined to assist in effective memory management within the bootloader environment. 13In this example's `memory.x` file, various symbols are defined to assist in effective memory management within the bootloader environment.
14For dual-bank STM32 devices, it's crucial to assign these symbols correctly to their respective memory banks. 14For dual-bank STM32 devices, it's crucial to assign these symbols correctly to their respective memory banks.
15 15
16### Symbol Definitions 16### Symbol Definitions
17 17
diff --git a/examples/rp/Cargo.toml b/examples/rp/Cargo.toml
index 585349506..0f58f143c 100644
--- a/examples/rp/Cargo.toml
+++ b/examples/rp/Cargo.toml
@@ -12,7 +12,7 @@ embassy-executor = { version = "0.5.0", path = "../../embassy-executor", feature
12embassy-time = { version = "0.3.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } 12embassy-time = { version = "0.3.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] }
13embassy-rp = { version = "0.1.0", path = "../../embassy-rp", features = ["defmt", "unstable-pac", "time-driver", "critical-section-impl"] } 13embassy-rp = { version = "0.1.0", path = "../../embassy-rp", features = ["defmt", "unstable-pac", "time-driver", "critical-section-impl"] }
14embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] } 14embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] }
15embassy-net = { version = "0.4.0", path = "../../embassy-net", features = ["defmt", "tcp", "udp", "dhcpv4", "medium-ethernet"] } 15embassy-net = { version = "0.4.0", path = "../../embassy-net", features = ["defmt", "tcp", "udp", "raw", "dhcpv4", "medium-ethernet"] }
16embassy-net-wiznet = { version = "0.1.0", path = "../../embassy-net-wiznet", features = ["defmt"] } 16embassy-net-wiznet = { version = "0.1.0", path = "../../embassy-net-wiznet", features = ["defmt"] }
17embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } 17embassy-futures = { version = "0.1.0", path = "../../embassy-futures" }
18embassy-usb-logger = { version = "0.1.0", path = "../../embassy-usb-logger" } 18embassy-usb-logger = { version = "0.1.0", path = "../../embassy-usb-logger" }
diff --git a/examples/stm32f0/src/bin/adc.rs b/examples/stm32f0/src/bin/adc.rs
index c2fb143cd..a5a4186ea 100644
--- a/examples/stm32f0/src/bin/adc.rs
+++ b/examples/stm32f0/src/bin/adc.rs
@@ -6,7 +6,7 @@ use embassy_executor::Spawner;
6use embassy_stm32::adc::{Adc, SampleTime}; 6use embassy_stm32::adc::{Adc, SampleTime};
7use embassy_stm32::peripherals::ADC; 7use embassy_stm32::peripherals::ADC;
8use embassy_stm32::{adc, bind_interrupts}; 8use embassy_stm32::{adc, bind_interrupts};
9use embassy_time::{Delay, Timer}; 9use embassy_time::Timer;
10use {defmt_rtt as _, panic_probe as _}; 10use {defmt_rtt as _, panic_probe as _};
11 11
12bind_interrupts!(struct Irqs { 12bind_interrupts!(struct Irqs {
@@ -18,11 +18,11 @@ async fn main(_spawner: Spawner) {
18 let p = embassy_stm32::init(Default::default()); 18 let p = embassy_stm32::init(Default::default());
19 info!("Hello World!"); 19 info!("Hello World!");
20 20
21 let mut adc = Adc::new(p.ADC, Irqs, &mut Delay); 21 let mut adc = Adc::new(p.ADC, Irqs);
22 adc.set_sample_time(SampleTime::CYCLES71_5); 22 adc.set_sample_time(SampleTime::CYCLES71_5);
23 let mut pin = p.PA1; 23 let mut pin = p.PA1;
24 24
25 let mut vrefint = adc.enable_vref(&mut Delay); 25 let mut vrefint = adc.enable_vref();
26 let vrefint_sample = adc.read(&mut vrefint).await; 26 let vrefint_sample = adc.read(&mut vrefint).await;
27 let convert_to_millivolts = |sample| { 27 let convert_to_millivolts = |sample| {
28 // From https://www.st.com/resource/en/datasheet/stm32f031c6.pdf 28 // From https://www.st.com/resource/en/datasheet/stm32f031c6.pdf
diff --git a/examples/stm32f0/src/bin/multiprio.rs b/examples/stm32f0/src/bin/multiprio.rs
index e49951726..1c3f3991a 100644
--- a/examples/stm32f0/src/bin/multiprio.rs
+++ b/examples/stm32f0/src/bin/multiprio.rs
@@ -126,6 +126,11 @@ fn main() -> ! {
126 // Initialize and create handle for devicer peripherals 126 // Initialize and create handle for devicer peripherals
127 let _p = embassy_stm32::init(Default::default()); 127 let _p = embassy_stm32::init(Default::default());
128 128
129 // STM32s don’t have any interrupts exclusively for software use, but they can all be triggered by software as well as
130 // by the peripheral, so we can just use any free interrupt vectors which aren’t used by the rest of your application.
131 // In this case we’re using UART1 and UART2, but there’s nothing special about them. Any otherwise unused interrupt
132 // vector would work exactly the same.
133
129 // High-priority executor: USART1, priority level 6 134 // High-priority executor: USART1, priority level 6
130 interrupt::USART1.set_priority(Priority::P6); 135 interrupt::USART1.set_priority(Priority::P6);
131 let spawner = EXECUTOR_HIGH.start(interrupt::USART1); 136 let spawner = EXECUTOR_HIGH.start(interrupt::USART1);
diff --git a/examples/stm32f1/src/bin/adc.rs b/examples/stm32f1/src/bin/adc.rs
index 1440460a9..541ff159e 100644
--- a/examples/stm32f1/src/bin/adc.rs
+++ b/examples/stm32f1/src/bin/adc.rs
@@ -6,7 +6,7 @@ use embassy_executor::Spawner;
6use embassy_stm32::adc::Adc; 6use embassy_stm32::adc::Adc;
7use embassy_stm32::peripherals::ADC1; 7use embassy_stm32::peripherals::ADC1;
8use embassy_stm32::{adc, bind_interrupts}; 8use embassy_stm32::{adc, bind_interrupts};
9use embassy_time::{Delay, Timer}; 9use embassy_time::Timer;
10use {defmt_rtt as _, panic_probe as _}; 10use {defmt_rtt as _, panic_probe as _};
11 11
12bind_interrupts!(struct Irqs { 12bind_interrupts!(struct Irqs {
@@ -18,10 +18,10 @@ async fn main(_spawner: Spawner) {
18 let p = embassy_stm32::init(Default::default()); 18 let p = embassy_stm32::init(Default::default());
19 info!("Hello World!"); 19 info!("Hello World!");
20 20
21 let mut adc = Adc::new(p.ADC1, &mut Delay); 21 let mut adc = Adc::new(p.ADC1);
22 let mut pin = p.PB1; 22 let mut pin = p.PB1;
23 23
24 let mut vrefint = adc.enable_vref(&mut Delay); 24 let mut vrefint = adc.enable_vref();
25 let vrefint_sample = adc.read(&mut vrefint).await; 25 let vrefint_sample = adc.read(&mut vrefint).await;
26 let convert_to_millivolts = |sample| { 26 let convert_to_millivolts = |sample| {
27 // From http://www.st.com/resource/en/datasheet/CD00161566.pdf 27 // From http://www.st.com/resource/en/datasheet/CD00161566.pdf
diff --git a/examples/stm32f3/src/bin/multiprio.rs b/examples/stm32f3/src/bin/multiprio.rs
index 328447210..87830b416 100644
--- a/examples/stm32f3/src/bin/multiprio.rs
+++ b/examples/stm32f3/src/bin/multiprio.rs
@@ -127,6 +127,11 @@ fn main() -> ! {
127 127
128 let _p = embassy_stm32::init(Default::default()); 128 let _p = embassy_stm32::init(Default::default());
129 129
130 // STM32s don’t have any interrupts exclusively for software use, but they can all be triggered by software as well as
131 // by the peripheral, so we can just use any free interrupt vectors which aren’t used by the rest of your application.
132 // In this case we’re using UART4 and UART5, but there’s nothing special about them. Any otherwise unused interrupt
133 // vector would work exactly the same.
134
130 // High-priority executor: UART4, priority level 6 135 // High-priority executor: UART4, priority level 6
131 interrupt::UART4.set_priority(Priority::P6); 136 interrupt::UART4.set_priority(Priority::P6);
132 let spawner = EXECUTOR_HIGH.start(interrupt::UART4); 137 let spawner = EXECUTOR_HIGH.start(interrupt::UART4);
diff --git a/examples/stm32f334/src/bin/adc.rs b/examples/stm32f334/src/bin/adc.rs
index bd126ce68..0528a9637 100644
--- a/examples/stm32f334/src/bin/adc.rs
+++ b/examples/stm32f334/src/bin/adc.rs
@@ -7,7 +7,7 @@ use embassy_stm32::adc::{Adc, SampleTime};
7use embassy_stm32::peripherals::ADC1; 7use embassy_stm32::peripherals::ADC1;
8use embassy_stm32::time::mhz; 8use embassy_stm32::time::mhz;
9use embassy_stm32::{adc, bind_interrupts, Config}; 9use embassy_stm32::{adc, bind_interrupts, Config};
10use embassy_time::{Delay, Timer}; 10use embassy_time::Timer;
11use {defmt_rtt as _, panic_probe as _}; 11use {defmt_rtt as _, panic_probe as _};
12 12
13bind_interrupts!(struct Irqs { 13bind_interrupts!(struct Irqs {
@@ -38,13 +38,13 @@ async fn main(_spawner: Spawner) -> ! {
38 38
39 info!("create adc..."); 39 info!("create adc...");
40 40
41 let mut adc = Adc::new(p.ADC1, Irqs, &mut Delay); 41 let mut adc = Adc::new(p.ADC1, Irqs);
42 42
43 adc.set_sample_time(SampleTime::CYCLES601_5); 43 adc.set_sample_time(SampleTime::CYCLES601_5);
44 44
45 info!("enable vrefint..."); 45 info!("enable vrefint...");
46 46
47 let mut vrefint = adc.enable_vref(&mut Delay); 47 let mut vrefint = adc.enable_vref();
48 let mut temperature = adc.enable_temperature(); 48 let mut temperature = adc.enable_temperature();
49 49
50 loop { 50 loop {
diff --git a/examples/stm32f334/src/bin/opamp.rs b/examples/stm32f334/src/bin/opamp.rs
index a5c710aa2..2dbf1bdab 100644
--- a/examples/stm32f334/src/bin/opamp.rs
+++ b/examples/stm32f334/src/bin/opamp.rs
@@ -8,7 +8,7 @@ use embassy_stm32::opamp::{OpAmp, OpAmpGain};
8use embassy_stm32::peripherals::ADC2; 8use embassy_stm32::peripherals::ADC2;
9use embassy_stm32::time::mhz; 9use embassy_stm32::time::mhz;
10use embassy_stm32::{adc, bind_interrupts, Config}; 10use embassy_stm32::{adc, bind_interrupts, Config};
11use embassy_time::{Delay, Timer}; 11use embassy_time::Timer;
12use {defmt_rtt as _, panic_probe as _}; 12use {defmt_rtt as _, panic_probe as _};
13 13
14bind_interrupts!(struct Irqs { 14bind_interrupts!(struct Irqs {
@@ -39,14 +39,14 @@ async fn main(_spawner: Spawner) -> ! {
39 39
40 info!("create adc..."); 40 info!("create adc...");
41 41
42 let mut adc = Adc::new(p.ADC2, Irqs, &mut Delay); 42 let mut adc = Adc::new(p.ADC2, Irqs);
43 let mut opamp = OpAmp::new(p.OPAMP2); 43 let mut opamp = OpAmp::new(p.OPAMP2);
44 44
45 adc.set_sample_time(SampleTime::CYCLES601_5); 45 adc.set_sample_time(SampleTime::CYCLES601_5);
46 46
47 info!("enable vrefint..."); 47 info!("enable vrefint...");
48 48
49 let mut vrefint = adc.enable_vref(&mut Delay); 49 let mut vrefint = adc.enable_vref();
50 let mut temperature = adc.enable_temperature(); 50 let mut temperature = adc.enable_temperature();
51 let mut buffer = opamp.buffer_ext(&mut p.PA7, &mut p.PA6, OpAmpGain::Mul1); 51 let mut buffer = opamp.buffer_ext(&mut p.PA7, &mut p.PA6, OpAmpGain::Mul1);
52 52
diff --git a/examples/stm32f4/src/bin/adc.rs b/examples/stm32f4/src/bin/adc.rs
index 699c29c05..9473b7b7f 100644
--- a/examples/stm32f4/src/bin/adc.rs
+++ b/examples/stm32f4/src/bin/adc.rs
@@ -14,7 +14,7 @@ async fn main(_spawner: Spawner) {
14 info!("Hello World!"); 14 info!("Hello World!");
15 15
16 let mut delay = Delay; 16 let mut delay = Delay;
17 let mut adc = Adc::new(p.ADC1, &mut delay); 17 let mut adc = Adc::new(p.ADC1);
18 let mut pin = p.PC1; 18 let mut pin = p.PC1;
19 19
20 let mut vrefint = adc.enable_vrefint(); 20 let mut vrefint = adc.enable_vrefint();
diff --git a/examples/stm32f4/src/bin/multiprio.rs b/examples/stm32f4/src/bin/multiprio.rs
index 328447210..87830b416 100644
--- a/examples/stm32f4/src/bin/multiprio.rs
+++ b/examples/stm32f4/src/bin/multiprio.rs
@@ -127,6 +127,11 @@ fn main() -> ! {
127 127
128 let _p = embassy_stm32::init(Default::default()); 128 let _p = embassy_stm32::init(Default::default());
129 129
130 // STM32s don’t have any interrupts exclusively for software use, but they can all be triggered by software as well as
131 // by the peripheral, so we can just use any free interrupt vectors which aren’t used by the rest of your application.
132 // In this case we’re using UART4 and UART5, but there’s nothing special about them. Any otherwise unused interrupt
133 // vector would work exactly the same.
134
130 // High-priority executor: UART4, priority level 6 135 // High-priority executor: UART4, priority level 6
131 interrupt::UART4.set_priority(Priority::P6); 136 interrupt::UART4.set_priority(Priority::P6);
132 let spawner = EXECUTOR_HIGH.start(interrupt::UART4); 137 let spawner = EXECUTOR_HIGH.start(interrupt::UART4);
diff --git a/examples/stm32f4/src/bin/usb_hid_keyboard.rs b/examples/stm32f4/src/bin/usb_hid_keyboard.rs
index a799b4e72..d6e0be5ea 100644
--- a/examples/stm32f4/src/bin/usb_hid_keyboard.rs
+++ b/examples/stm32f4/src/bin/usb_hid_keyboard.rs
@@ -49,6 +49,7 @@ async fn main(_spawner: Spawner) {
49 // Create the driver, from the HAL. 49 // Create the driver, from the HAL.
50 let mut ep_out_buffer = [0u8; 256]; 50 let mut ep_out_buffer = [0u8; 256];
51 let mut config = embassy_stm32::usb::Config::default(); 51 let mut config = embassy_stm32::usb::Config::default();
52 // If the board you’re using doesn’t have the VBUS pin wired up correctly for detecting the USB bus voltage (e.g. on the f4 blackpill board), set this to false
52 config.vbus_detection = true; 53 config.vbus_detection = true;
53 let driver = Driver::new_fs(p.USB_OTG_FS, Irqs, p.PA12, p.PA11, &mut ep_out_buffer, config); 54 let driver = Driver::new_fs(p.USB_OTG_FS, Irqs, p.PA12, p.PA11, &mut ep_out_buffer, config);
54 55
diff --git a/examples/stm32f4/src/bin/ws2812_spi.rs b/examples/stm32f4/src/bin/ws2812_spi.rs
index a280a3b77..56ccb67b8 100644
--- a/examples/stm32f4/src/bin/ws2812_spi.rs
+++ b/examples/stm32f4/src/bin/ws2812_spi.rs
@@ -8,7 +8,7 @@
8// If you want to save SPI for other purpose, you may want to take a look at `ws2812_pwm_dma.rs` file, which make use of TIM and DMA. 8// If you want to save SPI for other purpose, you may want to take a look at `ws2812_pwm_dma.rs` file, which make use of TIM and DMA.
9// 9//
10// Warning: 10// Warning:
11// DO NOT stare at ws2812 directy (especially after each MCU Reset), its (max) brightness could easily make your eyes feel burn. 11// DO NOT stare at ws2812 directly (especially after each MCU Reset), its (max) brightness could easily make your eyes feel burn.
12 12
13#![no_std] 13#![no_std]
14#![no_main] 14#![no_main]
diff --git a/examples/stm32f7/src/bin/adc.rs b/examples/stm32f7/src/bin/adc.rs
index f8d7b691f..641157960 100644
--- a/examples/stm32f7/src/bin/adc.rs
+++ b/examples/stm32f7/src/bin/adc.rs
@@ -4,7 +4,7 @@
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::adc::Adc; 6use embassy_stm32::adc::Adc;
7use embassy_time::{Delay, Timer}; 7use embassy_time::Timer;
8use {defmt_rtt as _, panic_probe as _}; 8use {defmt_rtt as _, panic_probe as _};
9 9
10#[embassy_executor::main] 10#[embassy_executor::main]
@@ -12,7 +12,7 @@ async fn main(_spawner: Spawner) {
12 let p = embassy_stm32::init(Default::default()); 12 let p = embassy_stm32::init(Default::default());
13 info!("Hello World!"); 13 info!("Hello World!");
14 14
15 let mut adc = Adc::new(p.ADC1, &mut Delay); 15 let mut adc = Adc::new(p.ADC1);
16 let mut pin = p.PA3; 16 let mut pin = p.PA3;
17 17
18 let mut vrefint = adc.enable_vrefint(); 18 let mut vrefint = adc.enable_vrefint();
diff --git a/examples/stm32g4/src/bin/adc.rs b/examples/stm32g4/src/bin/adc.rs
index ae64bc8e4..3de38cbd6 100644
--- a/examples/stm32g4/src/bin/adc.rs
+++ b/examples/stm32g4/src/bin/adc.rs
@@ -5,7 +5,7 @@ use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::adc::{Adc, SampleTime}; 6use embassy_stm32::adc::{Adc, SampleTime};
7use embassy_stm32::Config; 7use embassy_stm32::Config;
8use embassy_time::{Delay, Timer}; 8use embassy_time::Timer;
9use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
10 10
11#[embassy_executor::main] 11#[embassy_executor::main]
@@ -28,8 +28,8 @@ async fn main(_spawner: Spawner) {
28 let mut p = embassy_stm32::init(config); 28 let mut p = embassy_stm32::init(config);
29 info!("Hello World!"); 29 info!("Hello World!");
30 30
31 let mut adc = Adc::new(p.ADC2, &mut Delay); 31 let mut adc = Adc::new(p.ADC2);
32 adc.set_sample_time(SampleTime::CYCLES32_5); 32 adc.set_sample_time(SampleTime::CYCLES24_5);
33 33
34 loop { 34 loop {
35 let measured = adc.read(&mut p.PA7); 35 let measured = adc.read(&mut p.PA7);
diff --git a/examples/stm32h7/src/bin/adc.rs b/examples/stm32h7/src/bin/adc.rs
index a5594d10c..0009103d1 100644
--- a/examples/stm32h7/src/bin/adc.rs
+++ b/examples/stm32h7/src/bin/adc.rs
@@ -5,7 +5,7 @@ use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::adc::{Adc, SampleTime}; 6use embassy_stm32::adc::{Adc, SampleTime};
7use embassy_stm32::Config; 7use embassy_stm32::Config;
8use embassy_time::{Delay, Timer}; 8use embassy_time::Timer;
9use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
10 10
11#[embassy_executor::main] 11#[embassy_executor::main]
@@ -44,7 +44,7 @@ async fn main(_spawner: Spawner) {
44 44
45 info!("Hello World!"); 45 info!("Hello World!");
46 46
47 let mut adc = Adc::new(p.ADC3, &mut Delay); 47 let mut adc = Adc::new(p.ADC3);
48 48
49 adc.set_sample_time(SampleTime::CYCLES32_5); 49 adc.set_sample_time(SampleTime::CYCLES32_5);
50 50
diff --git a/examples/stm32h7/src/bin/multiprio.rs b/examples/stm32h7/src/bin/multiprio.rs
index 73f8dd092..fcbb6c653 100644
--- a/examples/stm32h7/src/bin/multiprio.rs
+++ b/examples/stm32h7/src/bin/multiprio.rs
@@ -127,6 +127,11 @@ fn main() -> ! {
127 127
128 let _p = embassy_stm32::init(Default::default()); 128 let _p = embassy_stm32::init(Default::default());
129 129
130 // STM32s don’t have any interrupts exclusively for software use, but they can all be triggered by software as well as
131 // by the peripheral, so we can just use any free interrupt vectors which aren’t used by the rest of your application.
132 // In this case we’re using UART4 and UART5, but there’s nothing special about them. Any otherwise unused interrupt
133 // vector would work exactly the same.
134
130 // High-priority executor: UART4, priority level 6 135 // High-priority executor: UART4, priority level 6
131 interrupt::UART4.set_priority(Priority::P6); 136 interrupt::UART4.set_priority(Priority::P6);
132 let spawner = EXECUTOR_HIGH.start(interrupt::UART4); 137 let spawner = EXECUTOR_HIGH.start(interrupt::UART4);
diff --git a/examples/stm32l0/src/bin/adc.rs b/examples/stm32l0/src/bin/adc.rs
index 97d41ca4b..507c3204a 100644
--- a/examples/stm32l0/src/bin/adc.rs
+++ b/examples/stm32l0/src/bin/adc.rs
@@ -6,7 +6,7 @@ use embassy_executor::Spawner;
6use embassy_stm32::adc::{Adc, SampleTime}; 6use embassy_stm32::adc::{Adc, SampleTime};
7use embassy_stm32::peripherals::ADC; 7use embassy_stm32::peripherals::ADC;
8use embassy_stm32::{adc, bind_interrupts}; 8use embassy_stm32::{adc, bind_interrupts};
9use embassy_time::{Delay, Timer}; 9use embassy_time::Timer;
10use {defmt_rtt as _, panic_probe as _}; 10use {defmt_rtt as _, panic_probe as _};
11 11
12bind_interrupts!(struct Irqs { 12bind_interrupts!(struct Irqs {
@@ -18,11 +18,11 @@ async fn main(_spawner: Spawner) {
18 let p = embassy_stm32::init(Default::default()); 18 let p = embassy_stm32::init(Default::default());
19 info!("Hello World!"); 19 info!("Hello World!");
20 20
21 let mut adc = Adc::new(p.ADC, Irqs, &mut Delay); 21 let mut adc = Adc::new(p.ADC, Irqs);
22 adc.set_sample_time(SampleTime::CYCLES79_5); 22 adc.set_sample_time(SampleTime::CYCLES79_5);
23 let mut pin = p.PA1; 23 let mut pin = p.PA1;
24 24
25 let mut vrefint = adc.enable_vref(&mut Delay); 25 let mut vrefint = adc.enable_vref();
26 let vrefint_sample = adc.read(&mut vrefint).await; 26 let vrefint_sample = adc.read(&mut vrefint).await;
27 let convert_to_millivolts = |sample| { 27 let convert_to_millivolts = |sample| {
28 // From https://www.st.com/resource/en/datasheet/stm32l051c6.pdf 28 // From https://www.st.com/resource/en/datasheet/stm32l051c6.pdf
diff --git a/examples/stm32l4/src/bin/adc.rs b/examples/stm32l4/src/bin/adc.rs
index a9f4604aa..7a89334e0 100644
--- a/examples/stm32l4/src/bin/adc.rs
+++ b/examples/stm32l4/src/bin/adc.rs
@@ -4,7 +4,6 @@
4use defmt::*; 4use defmt::*;
5use embassy_stm32::adc::{Adc, Resolution}; 5use embassy_stm32::adc::{Adc, Resolution};
6use embassy_stm32::Config; 6use embassy_stm32::Config;
7use embassy_time::Delay;
8use {defmt_rtt as _, panic_probe as _}; 7use {defmt_rtt as _, panic_probe as _};
9 8
10#[cortex_m_rt::entry] 9#[cortex_m_rt::entry]
@@ -18,7 +17,7 @@ fn main() -> ! {
18 } 17 }
19 let p = embassy_stm32::init(config); 18 let p = embassy_stm32::init(config);
20 19
21 let mut adc = Adc::new(p.ADC1, &mut Delay); 20 let mut adc = Adc::new(p.ADC1);
22 //adc.enable_vref(); 21 //adc.enable_vref();
23 adc.set_resolution(Resolution::BITS8); 22 adc.set_resolution(Resolution::BITS8);
24 let mut channel = p.PC0; 23 let mut channel = p.PC0;
diff --git a/examples/stm32u0/.cargo/config.toml b/examples/stm32u0/.cargo/config.toml
new file mode 100644
index 000000000..688347084
--- /dev/null
+++ b/examples/stm32u0/.cargo/config.toml
@@ -0,0 +1,9 @@
1[target.'cfg(all(target_arch = "arm", target_os = "none"))']
2# replace stm32u083rctx with your chip as listed in `probe-rs chip list`
3runner = "probe-rs run --chip stm32u083rctx"
4
5[build]
6target = "thumbv6m-none-eabi"
7
8[env]
9DEFMT_LOG = "trace"
diff --git a/examples/stm32u0/Cargo.toml b/examples/stm32u0/Cargo.toml
new file mode 100644
index 000000000..495be3e75
--- /dev/null
+++ b/examples/stm32u0/Cargo.toml
@@ -0,0 +1,25 @@
1[package]
2edition = "2021"
3name = "embassy-stm32u0-examples"
4version = "0.1.0"
5license = "MIT OR Apache-2.0"
6
7[dependencies]
8# Change stm32u083rc to your chip name, if necessary.
9embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = [ "defmt", "time-driver-any", "stm32u083rc", "memory-x", "unstable-pac", "exti"] }
10embassy-sync = { version = "0.5.0", path = "../../embassy-sync", features = ["defmt"] }
11embassy-executor = { version = "0.5.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] }
12embassy-time = { version = "0.3.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
13
14defmt = "0.3"
15defmt-rtt = "0.4"
16
17cortex-m = { version = "0.7.6", features = ["critical-section-single-core"] }
18cortex-m-rt = "0.7.0"
19embedded-hal = "0.2.6"
20panic-probe = { version = "0.3", features = ["print-defmt"] }
21futures = { version = "0.3.17", default-features = false, features = ["async-await"] }
22heapless = { version = "0.8", default-features = false }
23
24[profile.release]
25debug = 2
diff --git a/examples/stm32u0/build.rs b/examples/stm32u0/build.rs
new file mode 100644
index 000000000..8cd32d7ed
--- /dev/null
+++ b/examples/stm32u0/build.rs
@@ -0,0 +1,5 @@
1fn main() {
2 println!("cargo:rustc-link-arg-bins=--nmagic");
3 println!("cargo:rustc-link-arg-bins=-Tlink.x");
4 println!("cargo:rustc-link-arg-bins=-Tdefmt.x");
5}
diff --git a/examples/stm32u0/src/bin/blinky.rs b/examples/stm32u0/src/bin/blinky.rs
new file mode 100644
index 000000000..90e479aae
--- /dev/null
+++ b/examples/stm32u0/src/bin/blinky.rs
@@ -0,0 +1,26 @@
1#![no_std]
2#![no_main]
3
4use defmt::*;
5use embassy_executor::Spawner;
6use embassy_stm32::gpio::{Level, Output, Speed};
7use embassy_time::Timer;
8use {defmt_rtt as _, panic_probe as _};
9
10#[embassy_executor::main]
11async fn main(_spawner: Spawner) {
12 let p = embassy_stm32::init(Default::default());
13 info!("Hello World!");
14
15 let mut led = Output::new(p.PA5, Level::High, Speed::Low);
16
17 loop {
18 info!("high");
19 led.set_high();
20 Timer::after_millis(300).await;
21
22 info!("low");
23 led.set_low();
24 Timer::after_millis(300).await;
25 }
26}
diff --git a/examples/stm32u0/src/bin/button.rs b/examples/stm32u0/src/bin/button.rs
new file mode 100644
index 000000000..8017f0274
--- /dev/null
+++ b/examples/stm32u0/src/bin/button.rs
@@ -0,0 +1,24 @@
1#![no_std]
2#![no_main]
3
4use cortex_m_rt::entry;
5use defmt::*;
6use embassy_stm32::gpio::{Input, Pull};
7use {defmt_rtt as _, panic_probe as _};
8
9#[entry]
10fn main() -> ! {
11 info!("Hello World!");
12
13 let p = embassy_stm32::init(Default::default());
14
15 let button = Input::new(p.PC13, Pull::Up);
16
17 loop {
18 if button.is_high() {
19 info!("high");
20 } else {
21 info!("low");
22 }
23 }
24}
diff --git a/examples/stm32u0/src/bin/button_exti.rs b/examples/stm32u0/src/bin/button_exti.rs
new file mode 100644
index 000000000..34a08bbc6
--- /dev/null
+++ b/examples/stm32u0/src/bin/button_exti.rs
@@ -0,0 +1,25 @@
1#![no_std]
2#![no_main]
3
4use defmt::*;
5use embassy_executor::Spawner;
6use embassy_stm32::exti::ExtiInput;
7use embassy_stm32::gpio::Pull;
8use {defmt_rtt as _, panic_probe as _};
9
10#[embassy_executor::main]
11async fn main(_spawner: Spawner) {
12 let p = embassy_stm32::init(Default::default());
13 info!("Hello World!");
14
15 let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Up);
16
17 info!("Press the USER button...");
18
19 loop {
20 button.wait_for_falling_edge().await;
21 info!("Pressed!");
22 button.wait_for_rising_edge().await;
23 info!("Released!");
24 }
25}
diff --git a/rust-toolchain-nightly.toml b/rust-toolchain-nightly.toml
index 98696fd2b..ac160b995 100644
--- a/rust-toolchain-nightly.toml
+++ b/rust-toolchain-nightly.toml
@@ -1,5 +1,5 @@
1[toolchain] 1[toolchain]
2channel = "nightly-2024-03-20" 2channel = "nightly-2024-04-14"
3components = [ "rust-src", "rustfmt", "llvm-tools", "miri" ] 3components = [ "rust-src", "rustfmt", "llvm-tools", "miri" ]
4targets = [ 4targets = [
5 "thumbv7em-none-eabi", 5 "thumbv7em-none-eabi",
diff --git a/tests/stm32/src/bin/dac.rs b/tests/stm32/src/bin/dac.rs
index 9d64742df..06501ab14 100644
--- a/tests/stm32/src/bin/dac.rs
+++ b/tests/stm32/src/bin/dac.rs
@@ -13,7 +13,7 @@ use embassy_executor::Spawner;
13use embassy_stm32::adc::Adc; 13use embassy_stm32::adc::Adc;
14use embassy_stm32::dac::{DacCh1, Value}; 14use embassy_stm32::dac::{DacCh1, Value};
15use embassy_stm32::dma::NoDma; 15use embassy_stm32::dma::NoDma;
16use embassy_time::{Delay, Timer}; 16use embassy_time::Timer;
17use micromath::F32Ext; 17use micromath::F32Ext;
18use {defmt_rtt as _, panic_probe as _}; 18use {defmt_rtt as _, panic_probe as _};
19 19
@@ -28,7 +28,7 @@ async fn main(_spawner: Spawner) {
28 let mut adc_pin = unsafe { core::ptr::read(&dac_pin) }; 28 let mut adc_pin = unsafe { core::ptr::read(&dac_pin) };
29 29
30 let mut dac = DacCh1::new(dac, NoDma, dac_pin); 30 let mut dac = DacCh1::new(dac, NoDma, dac_pin);
31 let mut adc = Adc::new(adc, &mut Delay); 31 let mut adc = Adc::new(adc);
32 32
33 #[cfg(feature = "stm32h755zi")] 33 #[cfg(feature = "stm32h755zi")]
34 let normalization_factor = 256; 34 let normalization_factor = 256;