diff options
| author | Tyler <[email protected]> | 2023-07-16 19:08:01 -0500 |
|---|---|---|
| committer | GitHub <[email protected]> | 2023-07-16 19:08:01 -0500 |
| commit | 6d8a5c6c20953c998df6ddd26906abe520df946d (patch) | |
| tree | 32cfdf85a1aa132cb0f1aac56a934ceed93fc597 | |
| parent | 3aedbce5c2775ff1ab10c3ca95ea1311043f4be4 (diff) | |
| parent | c7ec45a004750f590c1d9ea4a721972efe133b8e (diff) | |
Merge pull request #2 from embassy-rs/main
Pull changes from base embassy repo
199 files changed, 4973 insertions, 954 deletions
diff --git a/.github/ci/doc.sh b/.github/ci/doc.sh index 1402e742f..9e9c78a42 100755 --- a/.github/ci/doc.sh +++ b/.github/ci/doc.sh | |||
| @@ -6,7 +6,7 @@ set -euo pipefail | |||
| 6 | export RUSTUP_HOME=/ci/cache/rustup | 6 | export RUSTUP_HOME=/ci/cache/rustup |
| 7 | export CARGO_HOME=/ci/cache/cargo | 7 | export CARGO_HOME=/ci/cache/cargo |
| 8 | export CARGO_TARGET_DIR=/ci/cache/target | 8 | export CARGO_TARGET_DIR=/ci/cache/target |
| 9 | export BUILDER_THREADS=6 | 9 | export BUILDER_THREADS=4 |
| 10 | export BUILDER_COMPRESS=true | 10 | export BUILDER_COMPRESS=true |
| 11 | 11 | ||
| 12 | # force rustup to download the toolchain before starting building. | 12 | # force rustup to download the toolchain before starting building. |
| @@ -15,30 +15,31 @@ export BUILDER_COMPRESS=true | |||
| 15 | # which makes rustup very sad | 15 | # which makes rustup very sad |
| 16 | rustc --version > /dev/null | 16 | rustc --version > /dev/null |
| 17 | 17 | ||
| 18 | docserver-builder -i ./embassy-stm32 -o crates/embassy-stm32/git.zup | 18 | docserver-builder -i ./embassy-stm32 -o webroot/crates/embassy-stm32/git.zup |
| 19 | docserver-builder -i ./embassy-boot/boot -o crates/embassy-boot/git.zup | 19 | docserver-builder -i ./embassy-boot/boot -o webroot/crates/embassy-boot/git.zup |
| 20 | docserver-builder -i ./embassy-boot/nrf -o crates/embassy-boot-nrf/git.zup | 20 | docserver-builder -i ./embassy-boot/nrf -o webroot/crates/embassy-boot-nrf/git.zup |
| 21 | docserver-builder -i ./embassy-boot/rp -o crates/embassy-boot-rp/git.zup | 21 | docserver-builder -i ./embassy-boot/rp -o webroot/crates/embassy-boot-rp/git.zup |
| 22 | docserver-builder -i ./embassy-boot/stm32 -o crates/embassy-boot-stm32/git.zup | 22 | docserver-builder -i ./embassy-boot/stm32 -o webroot/crates/embassy-boot-stm32/git.zup |
| 23 | docserver-builder -i ./embassy-embedded-hal -o crates/embassy-embedded-hal/git.zup | 23 | docserver-builder -i ./embassy-embedded-hal -o webroot/crates/embassy-embedded-hal/git.zup |
| 24 | docserver-builder -i ./embassy-executor -o crates/embassy-executor/git.zup | 24 | docserver-builder -i ./embassy-executor -o webroot/crates/embassy-executor/git.zup |
| 25 | docserver-builder -i ./embassy-futures -o crates/embassy-futures/git.zup | 25 | docserver-builder -i ./embassy-futures -o webroot/crates/embassy-futures/git.zup |
| 26 | docserver-builder -i ./embassy-lora -o crates/embassy-lora/git.zup | 26 | docserver-builder -i ./embassy-lora -o webroot/crates/embassy-lora/git.zup |
| 27 | docserver-builder -i ./embassy-net -o crates/embassy-net/git.zup | 27 | docserver-builder -i ./embassy-net -o webroot/crates/embassy-net/git.zup |
| 28 | docserver-builder -i ./embassy-net-driver -o crates/embassy-net-driver/git.zup | 28 | docserver-builder -i ./embassy-net-driver -o webroot/crates/embassy-net-driver/git.zup |
| 29 | docserver-builder -i ./embassy-net-driver-channel -o crates/embassy-net-driver-channel/git.zup | 29 | docserver-builder -i ./embassy-net-driver-channel -o webroot/crates/embassy-net-driver-channel/git.zup |
| 30 | docserver-builder -i ./embassy-nrf -o crates/embassy-nrf/git.zup | 30 | docserver-builder -i ./embassy-nrf -o webroot/crates/embassy-nrf/git.zup |
| 31 | docserver-builder -i ./embassy-rp -o crates/embassy-rp/git.zup | 31 | docserver-builder -i ./embassy-rp -o webroot/crates/embassy-rp/git.zup |
| 32 | docserver-builder -i ./embassy-sync -o crates/embassy-sync/git.zup | 32 | docserver-builder -i ./embassy-sync -o webroot/crates/embassy-sync/git.zup |
| 33 | docserver-builder -i ./embassy-time -o crates/embassy-time/git.zup | 33 | docserver-builder -i ./embassy-time -o webroot/crates/embassy-time/git.zup |
| 34 | docserver-builder -i ./embassy-usb -o crates/embassy-usb/git.zup | 34 | docserver-builder -i ./embassy-usb -o webroot/crates/embassy-usb/git.zup |
| 35 | docserver-builder -i ./embassy-usb-driver -o crates/embassy-usb-driver/git.zup | 35 | docserver-builder -i ./embassy-usb-driver -o webroot/crates/embassy-usb-driver/git.zup |
| 36 | docserver-builder -i ./embassy-usb-logger -o crates/embassy-usb-logger/git.zup | 36 | docserver-builder -i ./embassy-usb-logger -o webroot/crates/embassy-usb-logger/git.zup |
| 37 | docserver-builder -i ./cyw43 -o crates/cyw43/git.zup | 37 | docserver-builder -i ./cyw43 -o webroot/crates/cyw43/git.zup |
| 38 | docserver-builder -i ./cyw43-pio -o crates/cyw43-pio/git.zup | 38 | docserver-builder -i ./cyw43-pio -o webroot/crates/cyw43-pio/git.zup |
| 39 | docserver-builder -i ./embassy-net-w5500 -o crates/embassy-net-w5500/git.zup | 39 | docserver-builder -i ./embassy-net-w5500 -o webroot/crates/embassy-net-w5500/git.zup |
| 40 | docserver-builder -i ./embassy-stm32-wpan -o crates/embassy-stm32-wpan/git.zup | 40 | docserver-builder -i ./embassy-stm32-wpan -o webroot/crates/embassy-stm32-wpan/git.zup --output-static webroot/static |
| 41 | 41 | ||
| 42 | export KUBECONFIG=/ci/secrets/kubeconfig.yml | 42 | export KUBECONFIG=/ci/secrets/kubeconfig.yml |
| 43 | POD=$(kubectl -n embassy get po -l app=docserver -o jsonpath={.items[0].metadata.name}) | 43 | POD=$(kubectl -n embassy get po -l app=docserver -o jsonpath={.items[0].metadata.name}) |
| 44 | kubectl cp crates $POD:/data | 44 | kubectl cp webroot/crates $POD:/data |
| 45 | kubectl cp webroot/static $POD:/data \ No newline at end of file | ||
| @@ -5,10 +5,6 @@ set -euo pipefail | |||
| 5 | export RUSTFLAGS=-Dwarnings | 5 | export RUSTFLAGS=-Dwarnings |
| 6 | export DEFMT_LOG=trace,embassy_net_esp_hosted=debug,cyw43=info,cyw43_pio=info,smoltcp=info | 6 | export DEFMT_LOG=trace,embassy_net_esp_hosted=debug,cyw43=info,cyw43_pio=info,smoltcp=info |
| 7 | 7 | ||
| 8 | # needed by wifi examples | ||
| 9 | export WIFI_NETWORK=x | ||
| 10 | export WIFI_PASSWORD=x | ||
| 11 | |||
| 12 | TARGET=$(rustc -vV | sed -n 's|host: ||p') | 8 | TARGET=$(rustc -vV | sed -n 's|host: ||p') |
| 13 | 9 | ||
| 14 | BUILD_EXTRA="" | 10 | BUILD_EXTRA="" |
diff --git a/cyw43/Cargo.toml b/cyw43/Cargo.toml index 61caa0272..50fb7c5db 100644 --- a/cyw43/Cargo.toml +++ b/cyw43/Cargo.toml | |||
| @@ -11,7 +11,7 @@ log = ["dep:log"] | |||
| 11 | firmware-logs = [] | 11 | firmware-logs = [] |
| 12 | 12 | ||
| 13 | [dependencies] | 13 | [dependencies] |
| 14 | embassy-time = { version = "0.1.0", path = "../embassy-time"} | 14 | embassy-time = { version = "0.1.2", path = "../embassy-time"} |
| 15 | embassy-sync = { version = "0.2.0", path = "../embassy-sync"} | 15 | embassy-sync = { version = "0.2.0", path = "../embassy-sync"} |
| 16 | embassy-futures = { version = "0.1.0", path = "../embassy-futures"} | 16 | embassy-futures = { version = "0.1.0", path = "../embassy-futures"} |
| 17 | embassy-net-driver-channel = { version = "0.1.0", path = "../embassy-net-driver-channel"} | 17 | embassy-net-driver-channel = { version = "0.1.0", path = "../embassy-net-driver-channel"} |
| @@ -24,7 +24,7 @@ cortex-m = "0.7.6" | |||
| 24 | cortex-m-rt = "0.7.0" | 24 | cortex-m-rt = "0.7.0" |
| 25 | futures = { version = "0.3.17", default-features = false, features = ["async-await", "cfg-target-has-atomic", "unstable"] } | 25 | futures = { version = "0.3.17", default-features = false, features = ["async-await", "cfg-target-has-atomic", "unstable"] } |
| 26 | 26 | ||
| 27 | embedded-hal-1 = { package = "embedded-hal", version = "1.0.0-alpha.10" } | 27 | embedded-hal-1 = { package = "embedded-hal", version = "1.0.0-alpha.11" } |
| 28 | num_enum = { version = "0.5.7", default-features = false } | 28 | num_enum = { version = "0.5.7", default-features = false } |
| 29 | 29 | ||
| 30 | [package.metadata.embassy_docs] | 30 | [package.metadata.embassy_docs] |
diff --git a/cyw43/README.md b/cyw43/README.md index e4a81410d..5b8f3cf40 100644 --- a/cyw43/README.md +++ b/cyw43/README.md | |||
| @@ -30,7 +30,7 @@ TODO: | |||
| 30 | ### Example 2: Create an access point (IP and credentials in the code) | 30 | ### Example 2: Create an access point (IP and credentials in the code) |
| 31 | - `cargo run --release --bin wifi_ap_tcp_server` | 31 | - `cargo run --release --bin wifi_ap_tcp_server` |
| 32 | ### Example 3: Connect to an existing network and create a server | 32 | ### Example 3: Connect to an existing network and create a server |
| 33 | - `WIFI_NETWORK=MyWifiNetwork WIFI_PASSWORD=MyWifiPassword cargo run --release --bin wifi_tcp_server` | 33 | - `cargo run --release --bin wifi_tcp_server` |
| 34 | 34 | ||
| 35 | After a few seconds, you should see that DHCP picks up an IP address like this | 35 | After a few seconds, you should see that DHCP picks up an IP address like this |
| 36 | ``` | 36 | ``` |
diff --git a/cyw43/src/runner.rs b/cyw43/src/runner.rs index 5706696b4..1c187faa5 100644 --- a/cyw43/src/runner.rs +++ b/cyw43/src/runner.rs | |||
| @@ -345,7 +345,9 @@ where | |||
| 345 | } | 345 | } |
| 346 | 346 | ||
| 347 | fn rx(&mut self, packet: &mut [u8]) { | 347 | fn rx(&mut self, packet: &mut [u8]) { |
| 348 | let Some((sdpcm_header, payload)) = SdpcmHeader::parse(packet) else { return }; | 348 | let Some((sdpcm_header, payload)) = SdpcmHeader::parse(packet) else { |
| 349 | return; | ||
| 350 | }; | ||
| 349 | 351 | ||
| 350 | self.update_credit(&sdpcm_header); | 352 | self.update_credit(&sdpcm_header); |
| 351 | 353 | ||
| @@ -353,7 +355,9 @@ where | |||
| 353 | 355 | ||
| 354 | match channel { | 356 | match channel { |
| 355 | CHANNEL_TYPE_CONTROL => { | 357 | CHANNEL_TYPE_CONTROL => { |
| 356 | let Some((cdc_header, response)) = CdcHeader::parse(payload) else { return; }; | 358 | let Some((cdc_header, response)) = CdcHeader::parse(payload) else { |
| 359 | return; | ||
| 360 | }; | ||
| 357 | trace!(" {:?}", cdc_header); | 361 | trace!(" {:?}", cdc_header); |
| 358 | 362 | ||
| 359 | if cdc_header.id == self.ioctl_id { | 363 | if cdc_header.id == self.ioctl_id { |
| @@ -417,8 +421,12 @@ where | |||
| 417 | let status = event_packet.msg.status; | 421 | let status = event_packet.msg.status; |
| 418 | let event_payload = match evt_type { | 422 | let event_payload = match evt_type { |
| 419 | Event::ESCAN_RESULT if status == EStatus::PARTIAL => { | 423 | Event::ESCAN_RESULT if status == EStatus::PARTIAL => { |
| 420 | let Some((_, bss_info)) = ScanResults::parse(evt_data) else { return }; | 424 | let Some((_, bss_info)) = ScanResults::parse(evt_data) else { |
| 421 | let Some(bss_info) = BssInfo::parse(bss_info) else { return }; | 425 | return; |
| 426 | }; | ||
| 427 | let Some(bss_info) = BssInfo::parse(bss_info) else { | ||
| 428 | return; | ||
| 429 | }; | ||
| 422 | events::Payload::BssInfo(*bss_info) | 430 | events::Payload::BssInfo(*bss_info) |
| 423 | } | 431 | } |
| 424 | Event::ESCAN_RESULT => events::Payload::None, | 432 | Event::ESCAN_RESULT => events::Payload::None, |
| @@ -439,7 +447,9 @@ where | |||
| 439 | } | 447 | } |
| 440 | } | 448 | } |
| 441 | CHANNEL_TYPE_DATA => { | 449 | CHANNEL_TYPE_DATA => { |
| 442 | let Some((_, packet)) = BdcHeader::parse(payload) else { return }; | 450 | let Some((_, packet)) = BdcHeader::parse(payload) else { |
| 451 | return; | ||
| 452 | }; | ||
| 443 | trace!("rx pkt {:02x}", Bytes(&packet[..packet.len().min(48)])); | 453 | trace!("rx pkt {:02x}", Bytes(&packet[..packet.len().min(48)])); |
| 444 | 454 | ||
| 445 | match self.ch.try_rx_buf() { | 455 | match self.ch.try_rx_buf() { |
diff --git a/embassy-embedded-hal/Cargo.toml b/embassy-embedded-hal/Cargo.toml index 35c70bb63..bba3d48be 100644 --- a/embassy-embedded-hal/Cargo.toml +++ b/embassy-embedded-hal/Cargo.toml | |||
| @@ -15,15 +15,18 @@ target = "x86_64-unknown-linux-gnu" | |||
| 15 | std = [] | 15 | std = [] |
| 16 | # Enable nightly-only features | 16 | # Enable nightly-only features |
| 17 | nightly = ["embassy-futures", "embedded-hal-async", "embedded-storage-async"] | 17 | nightly = ["embassy-futures", "embedded-hal-async", "embedded-storage-async"] |
| 18 | time = ["dep:embassy-time"] | ||
| 19 | default = ["time"] | ||
| 18 | 20 | ||
| 19 | [dependencies] | 21 | [dependencies] |
| 20 | embassy-futures = { version = "0.1.0", path = "../embassy-futures", optional = true } | 22 | embassy-futures = { version = "0.1.0", path = "../embassy-futures", optional = true } |
| 21 | embassy-sync = { version = "0.2.0", path = "../embassy-sync" } | 23 | embassy-sync = { version = "0.2.0", path = "../embassy-sync" } |
| 24 | embassy-time = { version = "0.1.2", path = "../embassy-time", optional = true } | ||
| 22 | embedded-hal-02 = { package = "embedded-hal", version = "0.2.6", features = [ | 25 | embedded-hal-02 = { package = "embedded-hal", version = "0.2.6", features = [ |
| 23 | "unproven", | 26 | "unproven", |
| 24 | ] } | 27 | ] } |
| 25 | embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-alpha.10" } | 28 | embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-alpha.11" } |
| 26 | embedded-hal-async = { version = "=0.2.0-alpha.1", optional = true } | 29 | embedded-hal-async = { version = "=0.2.0-alpha.2", optional = true } |
| 27 | embedded-storage = "0.3.0" | 30 | embedded-storage = "0.3.0" |
| 28 | embedded-storage-async = { version = "0.4.0", optional = true } | 31 | embedded-storage-async = { version = "0.4.0", optional = true } |
| 29 | nb = "1.0.0" | 32 | nb = "1.0.0" |
diff --git a/embassy-embedded-hal/src/adapter/blocking_async.rs b/embassy-embedded-hal/src/adapter/blocking_async.rs index b996d6a75..98ae2b02c 100644 --- a/embassy-embedded-hal/src/adapter/blocking_async.rs +++ b/embassy-embedded-hal/src/adapter/blocking_async.rs | |||
| @@ -74,47 +74,30 @@ where | |||
| 74 | E: embedded_hal_1::spi::Error + 'static, | 74 | E: embedded_hal_1::spi::Error + 'static, |
| 75 | T: blocking::spi::Transfer<u8, Error = E> + blocking::spi::Write<u8, Error = E>, | 75 | T: blocking::spi::Transfer<u8, Error = E> + blocking::spi::Write<u8, Error = E>, |
| 76 | { | 76 | { |
| 77 | async fn transfer<'a>(&'a mut self, read: &'a mut [u8], write: &'a [u8]) -> Result<(), Self::Error> { | 77 | async fn flush(&mut self) -> Result<(), Self::Error> { |
| 78 | // Ensure we write the expected bytes | ||
| 79 | for i in 0..core::cmp::min(read.len(), write.len()) { | ||
| 80 | read[i] = write[i].clone(); | ||
| 81 | } | ||
| 82 | self.wrapped.transfer(read)?; | ||
| 83 | Ok(()) | 78 | Ok(()) |
| 84 | } | 79 | } |
| 85 | 80 | ||
| 86 | async fn transfer_in_place<'a>(&'a mut self, _: &'a mut [u8]) -> Result<(), Self::Error> { | 81 | async fn write(&mut self, data: &[u8]) -> Result<(), Self::Error> { |
| 87 | todo!() | 82 | self.wrapped.write(data)?; |
| 83 | Ok(()) | ||
| 88 | } | 84 | } |
| 89 | } | ||
| 90 | 85 | ||
| 91 | impl<T, E> embedded_hal_async::spi::SpiBusFlush for BlockingAsync<T> | 86 | async fn read(&mut self, data: &mut [u8]) -> Result<(), Self::Error> { |
| 92 | where | 87 | self.wrapped.transfer(data)?; |
| 93 | E: embedded_hal_1::spi::Error + 'static, | ||
| 94 | T: blocking::spi::Transfer<u8, Error = E> + blocking::spi::Write<u8, Error = E>, | ||
| 95 | { | ||
| 96 | async fn flush(&mut self) -> Result<(), Self::Error> { | ||
| 97 | Ok(()) | 88 | Ok(()) |
| 98 | } | 89 | } |
| 99 | } | ||
| 100 | 90 | ||
| 101 | impl<T, E> embedded_hal_async::spi::SpiBusWrite<u8> for BlockingAsync<T> | 91 | async fn transfer(&mut self, read: &mut [u8], write: &[u8]) -> Result<(), Self::Error> { |
| 102 | where | 92 | // Ensure we write the expected bytes |
| 103 | E: embedded_hal_1::spi::Error + 'static, | 93 | for i in 0..core::cmp::min(read.len(), write.len()) { |
| 104 | T: blocking::spi::Transfer<u8, Error = E> + blocking::spi::Write<u8, Error = E>, | 94 | read[i] = write[i].clone(); |
| 105 | { | 95 | } |
| 106 | async fn write(&mut self, data: &[u8]) -> Result<(), Self::Error> { | 96 | self.wrapped.transfer(read)?; |
| 107 | self.wrapped.write(data)?; | ||
| 108 | Ok(()) | 97 | Ok(()) |
| 109 | } | 98 | } |
| 110 | } | ||
| 111 | 99 | ||
| 112 | impl<T, E> embedded_hal_async::spi::SpiBusRead<u8> for BlockingAsync<T> | 100 | async fn transfer_in_place(&mut self, data: &mut [u8]) -> Result<(), Self::Error> { |
| 113 | where | ||
| 114 | E: embedded_hal_1::spi::Error + 'static, | ||
| 115 | T: blocking::spi::Transfer<u8, Error = E> + blocking::spi::Write<u8, Error = E>, | ||
| 116 | { | ||
| 117 | async fn read(&mut self, data: &mut [u8]) -> Result<(), Self::Error> { | ||
| 118 | self.wrapped.transfer(data)?; | 101 | self.wrapped.transfer(data)?; |
| 119 | Ok(()) | 102 | Ok(()) |
| 120 | } | 103 | } |
diff --git a/embassy-embedded-hal/src/adapter/yielding_async.rs b/embassy-embedded-hal/src/adapter/yielding_async.rs index f51e4076f..fe9c9c341 100644 --- a/embassy-embedded-hal/src/adapter/yielding_async.rs +++ b/embassy-embedded-hal/src/adapter/yielding_async.rs | |||
| @@ -69,51 +69,36 @@ where | |||
| 69 | type Error = T::Error; | 69 | type Error = T::Error; |
| 70 | } | 70 | } |
| 71 | 71 | ||
| 72 | impl<T> embedded_hal_async::spi::SpiBus<u8> for YieldingAsync<T> | 72 | impl<T, Word: 'static + Copy> embedded_hal_async::spi::SpiBus<Word> for YieldingAsync<T> |
| 73 | where | 73 | where |
| 74 | T: embedded_hal_async::spi::SpiBus, | 74 | T: embedded_hal_async::spi::SpiBus<Word>, |
| 75 | { | 75 | { |
| 76 | async fn transfer<'a>(&'a mut self, read: &'a mut [u8], write: &'a [u8]) -> Result<(), Self::Error> { | 76 | async fn flush(&mut self) -> Result<(), Self::Error> { |
| 77 | self.wrapped.transfer(read, write).await?; | 77 | self.wrapped.flush().await?; |
| 78 | yield_now().await; | 78 | yield_now().await; |
| 79 | Ok(()) | 79 | Ok(()) |
| 80 | } | 80 | } |
| 81 | 81 | ||
| 82 | async fn transfer_in_place<'a>(&'a mut self, words: &'a mut [u8]) -> Result<(), Self::Error> { | 82 | async fn write(&mut self, data: &[Word]) -> Result<(), Self::Error> { |
| 83 | self.wrapped.transfer_in_place(words).await?; | 83 | self.wrapped.write(data).await?; |
| 84 | yield_now().await; | 84 | yield_now().await; |
| 85 | Ok(()) | 85 | Ok(()) |
| 86 | } | 86 | } |
| 87 | } | ||
| 88 | 87 | ||
| 89 | impl<T> embedded_hal_async::spi::SpiBusFlush for YieldingAsync<T> | 88 | async fn read(&mut self, data: &mut [Word]) -> Result<(), Self::Error> { |
| 90 | where | 89 | self.wrapped.read(data).await?; |
| 91 | T: embedded_hal_async::spi::SpiBusFlush, | ||
| 92 | { | ||
| 93 | async fn flush(&mut self) -> Result<(), Self::Error> { | ||
| 94 | self.wrapped.flush().await?; | ||
| 95 | yield_now().await; | 90 | yield_now().await; |
| 96 | Ok(()) | 91 | Ok(()) |
| 97 | } | 92 | } |
| 98 | } | ||
| 99 | 93 | ||
| 100 | impl<T> embedded_hal_async::spi::SpiBusWrite<u8> for YieldingAsync<T> | 94 | async fn transfer(&mut self, read: &mut [Word], write: &[Word]) -> Result<(), Self::Error> { |
| 101 | where | 95 | self.wrapped.transfer(read, write).await?; |
| 102 | T: embedded_hal_async::spi::SpiBusWrite<u8>, | ||
| 103 | { | ||
| 104 | async fn write(&mut self, data: &[u8]) -> Result<(), Self::Error> { | ||
| 105 | self.wrapped.write(data).await?; | ||
| 106 | yield_now().await; | 96 | yield_now().await; |
| 107 | Ok(()) | 97 | Ok(()) |
| 108 | } | 98 | } |
| 109 | } | ||
| 110 | 99 | ||
| 111 | impl<T> embedded_hal_async::spi::SpiBusRead<u8> for YieldingAsync<T> | 100 | async fn transfer_in_place(&mut self, words: &mut [Word]) -> Result<(), Self::Error> { |
| 112 | where | 101 | self.wrapped.transfer_in_place(words).await?; |
| 113 | T: embedded_hal_async::spi::SpiBusRead<u8>, | ||
| 114 | { | ||
| 115 | async fn read(&mut self, data: &mut [u8]) -> Result<(), Self::Error> { | ||
| 116 | self.wrapped.read(data).await?; | ||
| 117 | yield_now().await; | 102 | yield_now().await; |
| 118 | Ok(()) | 103 | Ok(()) |
| 119 | } | 104 | } |
diff --git a/embassy-embedded-hal/src/shared_bus/asynch/spi.rs b/embassy-embedded-hal/src/shared_bus/asynch/spi.rs index b5549a6cd..030392183 100644 --- a/embassy-embedded-hal/src/shared_bus/asynch/spi.rs +++ b/embassy-embedded-hal/src/shared_bus/asynch/spi.rs | |||
| @@ -56,62 +56,6 @@ where | |||
| 56 | type Error = SpiDeviceError<BUS::Error, CS::Error>; | 56 | type Error = SpiDeviceError<BUS::Error, CS::Error>; |
| 57 | } | 57 | } |
| 58 | 58 | ||
| 59 | impl<M, BUS, CS> spi::SpiDeviceRead for SpiDevice<'_, M, BUS, CS> | ||
| 60 | where | ||
| 61 | M: RawMutex, | ||
| 62 | BUS: spi::SpiBusRead, | ||
| 63 | CS: OutputPin, | ||
| 64 | { | ||
| 65 | async fn read_transaction(&mut self, operations: &mut [&mut [u8]]) -> Result<(), Self::Error> { | ||
| 66 | let mut bus = self.bus.lock().await; | ||
| 67 | self.cs.set_low().map_err(SpiDeviceError::Cs)?; | ||
| 68 | |||
| 69 | let op_res: Result<(), BUS::Error> = try { | ||
| 70 | for buf in operations { | ||
| 71 | bus.read(buf).await?; | ||
| 72 | } | ||
| 73 | }; | ||
| 74 | |||
| 75 | // On failure, it's important to still flush and deassert CS. | ||
| 76 | let flush_res = bus.flush().await; | ||
| 77 | let cs_res = self.cs.set_high(); | ||
| 78 | |||
| 79 | let op_res = op_res.map_err(SpiDeviceError::Spi)?; | ||
| 80 | flush_res.map_err(SpiDeviceError::Spi)?; | ||
| 81 | cs_res.map_err(SpiDeviceError::Cs)?; | ||
| 82 | |||
| 83 | Ok(op_res) | ||
| 84 | } | ||
| 85 | } | ||
| 86 | |||
| 87 | impl<M, BUS, CS> spi::SpiDeviceWrite for SpiDevice<'_, M, BUS, CS> | ||
| 88 | where | ||
| 89 | M: RawMutex, | ||
| 90 | BUS: spi::SpiBusWrite, | ||
| 91 | CS: OutputPin, | ||
| 92 | { | ||
| 93 | async fn write_transaction(&mut self, operations: &[&[u8]]) -> Result<(), Self::Error> { | ||
| 94 | let mut bus = self.bus.lock().await; | ||
| 95 | self.cs.set_low().map_err(SpiDeviceError::Cs)?; | ||
| 96 | |||
| 97 | let op_res: Result<(), BUS::Error> = try { | ||
| 98 | for buf in operations { | ||
| 99 | bus.write(buf).await?; | ||
| 100 | } | ||
| 101 | }; | ||
| 102 | |||
| 103 | // On failure, it's important to still flush and deassert CS. | ||
| 104 | let flush_res = bus.flush().await; | ||
| 105 | let cs_res = self.cs.set_high(); | ||
| 106 | |||
| 107 | let op_res = op_res.map_err(SpiDeviceError::Spi)?; | ||
| 108 | flush_res.map_err(SpiDeviceError::Spi)?; | ||
| 109 | cs_res.map_err(SpiDeviceError::Cs)?; | ||
| 110 | |||
| 111 | Ok(op_res) | ||
| 112 | } | ||
| 113 | } | ||
| 114 | |||
| 115 | impl<M, BUS, CS> spi::SpiDevice for SpiDevice<'_, M, BUS, CS> | 59 | impl<M, BUS, CS> spi::SpiDevice for SpiDevice<'_, M, BUS, CS> |
| 116 | where | 60 | where |
| 117 | M: RawMutex, | 61 | M: RawMutex, |
| @@ -129,6 +73,12 @@ where | |||
| 129 | Operation::Write(buf) => bus.write(buf).await?, | 73 | Operation::Write(buf) => bus.write(buf).await?, |
| 130 | Operation::Transfer(read, write) => bus.transfer(read, write).await?, | 74 | Operation::Transfer(read, write) => bus.transfer(read, write).await?, |
| 131 | Operation::TransferInPlace(buf) => bus.transfer_in_place(buf).await?, | 75 | Operation::TransferInPlace(buf) => bus.transfer_in_place(buf).await?, |
| 76 | #[cfg(not(feature = "time"))] | ||
| 77 | Operation::DelayUs(_) => return Err(SpiDeviceError::DelayUsNotSupported), | ||
| 78 | #[cfg(feature = "time")] | ||
| 79 | Operation::DelayUs(us) => { | ||
| 80 | embassy_time::Timer::after(embassy_time::Duration::from_micros(*us as _)).await | ||
| 81 | } | ||
| 132 | } | 82 | } |
| 133 | } | 83 | } |
| 134 | }; | 84 | }; |
| @@ -172,64 +122,6 @@ where | |||
| 172 | type Error = SpiDeviceError<BUS::Error, CS::Error>; | 122 | type Error = SpiDeviceError<BUS::Error, CS::Error>; |
| 173 | } | 123 | } |
| 174 | 124 | ||
| 175 | impl<M, BUS, CS> spi::SpiDeviceWrite for SpiDeviceWithConfig<'_, M, BUS, CS> | ||
| 176 | where | ||
| 177 | M: RawMutex, | ||
| 178 | BUS: spi::SpiBusWrite + SetConfig, | ||
| 179 | CS: OutputPin, | ||
| 180 | { | ||
| 181 | async fn write_transaction(&mut self, operations: &[&[u8]]) -> Result<(), Self::Error> { | ||
| 182 | let mut bus = self.bus.lock().await; | ||
| 183 | bus.set_config(&self.config); | ||
| 184 | self.cs.set_low().map_err(SpiDeviceError::Cs)?; | ||
| 185 | |||
| 186 | let op_res: Result<(), BUS::Error> = try { | ||
| 187 | for buf in operations { | ||
| 188 | bus.write(buf).await?; | ||
| 189 | } | ||
| 190 | }; | ||
| 191 | |||
| 192 | // On failure, it's important to still flush and deassert CS. | ||
| 193 | let flush_res = bus.flush().await; | ||
| 194 | let cs_res = self.cs.set_high(); | ||
| 195 | |||
| 196 | let op_res = op_res.map_err(SpiDeviceError::Spi)?; | ||
| 197 | flush_res.map_err(SpiDeviceError::Spi)?; | ||
| 198 | cs_res.map_err(SpiDeviceError::Cs)?; | ||
| 199 | |||
| 200 | Ok(op_res) | ||
| 201 | } | ||
| 202 | } | ||
| 203 | |||
| 204 | impl<M, BUS, CS> spi::SpiDeviceRead for SpiDeviceWithConfig<'_, M, BUS, CS> | ||
| 205 | where | ||
| 206 | M: RawMutex, | ||
| 207 | BUS: spi::SpiBusRead + SetConfig, | ||
| 208 | CS: OutputPin, | ||
| 209 | { | ||
| 210 | async fn read_transaction(&mut self, operations: &mut [&mut [u8]]) -> Result<(), Self::Error> { | ||
| 211 | let mut bus = self.bus.lock().await; | ||
| 212 | bus.set_config(&self.config); | ||
| 213 | self.cs.set_low().map_err(SpiDeviceError::Cs)?; | ||
| 214 | |||
| 215 | let op_res: Result<(), BUS::Error> = try { | ||
| 216 | for buf in operations { | ||
| 217 | bus.read(buf).await?; | ||
| 218 | } | ||
| 219 | }; | ||
| 220 | |||
| 221 | // On failure, it's important to still flush and deassert CS. | ||
| 222 | let flush_res = bus.flush().await; | ||
| 223 | let cs_res = self.cs.set_high(); | ||
| 224 | |||
| 225 | let op_res = op_res.map_err(SpiDeviceError::Spi)?; | ||
| 226 | flush_res.map_err(SpiDeviceError::Spi)?; | ||
| 227 | cs_res.map_err(SpiDeviceError::Cs)?; | ||
| 228 | |||
| 229 | Ok(op_res) | ||
| 230 | } | ||
| 231 | } | ||
| 232 | |||
| 233 | impl<M, BUS, CS> spi::SpiDevice for SpiDeviceWithConfig<'_, M, BUS, CS> | 125 | impl<M, BUS, CS> spi::SpiDevice for SpiDeviceWithConfig<'_, M, BUS, CS> |
| 234 | where | 126 | where |
| 235 | M: RawMutex, | 127 | M: RawMutex, |
| @@ -248,6 +140,12 @@ where | |||
| 248 | Operation::Write(buf) => bus.write(buf).await?, | 140 | Operation::Write(buf) => bus.write(buf).await?, |
| 249 | Operation::Transfer(read, write) => bus.transfer(read, write).await?, | 141 | Operation::Transfer(read, write) => bus.transfer(read, write).await?, |
| 250 | Operation::TransferInPlace(buf) => bus.transfer_in_place(buf).await?, | 142 | Operation::TransferInPlace(buf) => bus.transfer_in_place(buf).await?, |
| 143 | #[cfg(not(feature = "time"))] | ||
| 144 | Operation::DelayUs(_) => return Err(SpiDeviceError::DelayUsNotSupported), | ||
| 145 | #[cfg(feature = "time")] | ||
| 146 | Operation::DelayUs(us) => { | ||
| 147 | embassy_time::Timer::after(embassy_time::Duration::from_micros(*us as _)).await | ||
| 148 | } | ||
| 251 | } | 149 | } |
| 252 | } | 150 | } |
| 253 | }; | 151 | }; |
diff --git a/embassy-embedded-hal/src/shared_bus/blocking/spi.rs b/embassy-embedded-hal/src/shared_bus/blocking/spi.rs index 22e013be9..6d03d6263 100644 --- a/embassy-embedded-hal/src/shared_bus/blocking/spi.rs +++ b/embassy-embedded-hal/src/shared_bus/blocking/spi.rs | |||
| @@ -22,7 +22,7 @@ use core::cell::RefCell; | |||
| 22 | use embassy_sync::blocking_mutex::raw::RawMutex; | 22 | use embassy_sync::blocking_mutex::raw::RawMutex; |
| 23 | use embassy_sync::blocking_mutex::Mutex; | 23 | use embassy_sync::blocking_mutex::Mutex; |
| 24 | use embedded_hal_1::digital::OutputPin; | 24 | use embedded_hal_1::digital::OutputPin; |
| 25 | use embedded_hal_1::spi::{self, Operation, SpiBus, SpiBusRead, SpiBusWrite}; | 25 | use embedded_hal_1::spi::{self, Operation, SpiBus}; |
| 26 | 26 | ||
| 27 | use crate::shared_bus::SpiDeviceError; | 27 | use crate::shared_bus::SpiDeviceError; |
| 28 | use crate::SetConfig; | 28 | use crate::SetConfig; |
| @@ -48,58 +48,6 @@ where | |||
| 48 | type Error = SpiDeviceError<BUS::Error, CS::Error>; | 48 | type Error = SpiDeviceError<BUS::Error, CS::Error>; |
| 49 | } | 49 | } |
| 50 | 50 | ||
| 51 | impl<BUS, M, CS> embedded_hal_1::spi::SpiDeviceRead for SpiDevice<'_, M, BUS, CS> | ||
| 52 | where | ||
| 53 | M: RawMutex, | ||
| 54 | BUS: SpiBusRead, | ||
| 55 | CS: OutputPin, | ||
| 56 | { | ||
| 57 | fn read_transaction(&mut self, operations: &mut [&mut [u8]]) -> Result<(), Self::Error> { | ||
| 58 | self.bus.lock(|bus| { | ||
| 59 | let mut bus = bus.borrow_mut(); | ||
| 60 | self.cs.set_low().map_err(SpiDeviceError::Cs)?; | ||
| 61 | |||
| 62 | let op_res = operations.iter_mut().try_for_each(|buf| bus.read(buf)); | ||
| 63 | |||
| 64 | // On failure, it's important to still flush and deassert CS. | ||
| 65 | let flush_res = bus.flush(); | ||
| 66 | let cs_res = self.cs.set_high(); | ||
| 67 | |||
| 68 | let op_res = op_res.map_err(SpiDeviceError::Spi)?; | ||
| 69 | flush_res.map_err(SpiDeviceError::Spi)?; | ||
| 70 | cs_res.map_err(SpiDeviceError::Cs)?; | ||
| 71 | |||
| 72 | Ok(op_res) | ||
| 73 | }) | ||
| 74 | } | ||
| 75 | } | ||
| 76 | |||
| 77 | impl<BUS, M, CS> embedded_hal_1::spi::SpiDeviceWrite for SpiDevice<'_, M, BUS, CS> | ||
| 78 | where | ||
| 79 | M: RawMutex, | ||
| 80 | BUS: SpiBusWrite, | ||
| 81 | CS: OutputPin, | ||
| 82 | { | ||
| 83 | fn write_transaction(&mut self, operations: &[&[u8]]) -> Result<(), Self::Error> { | ||
| 84 | self.bus.lock(|bus| { | ||
| 85 | let mut bus = bus.borrow_mut(); | ||
| 86 | self.cs.set_low().map_err(SpiDeviceError::Cs)?; | ||
| 87 | |||
| 88 | let op_res = operations.iter().try_for_each(|buf| bus.write(buf)); | ||
| 89 | |||
| 90 | // On failure, it's important to still flush and deassert CS. | ||
| 91 | let flush_res = bus.flush(); | ||
| 92 | let cs_res = self.cs.set_high(); | ||
| 93 | |||
| 94 | let op_res = op_res.map_err(SpiDeviceError::Spi)?; | ||
| 95 | flush_res.map_err(SpiDeviceError::Spi)?; | ||
| 96 | cs_res.map_err(SpiDeviceError::Cs)?; | ||
| 97 | |||
| 98 | Ok(op_res) | ||
| 99 | }) | ||
| 100 | } | ||
| 101 | } | ||
| 102 | |||
| 103 | impl<BUS, M, CS> embedded_hal_1::spi::SpiDevice for SpiDevice<'_, M, BUS, CS> | 51 | impl<BUS, M, CS> embedded_hal_1::spi::SpiDevice for SpiDevice<'_, M, BUS, CS> |
| 104 | where | 52 | where |
| 105 | M: RawMutex, | 53 | M: RawMutex, |
| @@ -116,6 +64,13 @@ where | |||
| 116 | Operation::Write(buf) => bus.write(buf), | 64 | Operation::Write(buf) => bus.write(buf), |
| 117 | Operation::Transfer(read, write) => bus.transfer(read, write), | 65 | Operation::Transfer(read, write) => bus.transfer(read, write), |
| 118 | Operation::TransferInPlace(buf) => bus.transfer_in_place(buf), | 66 | Operation::TransferInPlace(buf) => bus.transfer_in_place(buf), |
| 67 | #[cfg(not(feature = "time"))] | ||
| 68 | Operation::DelayUs(_) => Err(SpiDeviceError::DelayUsNotSupported), | ||
| 69 | #[cfg(feature = "time")] | ||
| 70 | Operation::DelayUs(us) => { | ||
| 71 | embassy_time::block_for(embassy_time::Duration::from_micros(*us as _)); | ||
| 72 | Ok(()) | ||
| 73 | } | ||
| 119 | }); | 74 | }); |
| 120 | 75 | ||
| 121 | // On failure, it's important to still flush and deassert CS. | 76 | // On failure, it's important to still flush and deassert CS. |
| @@ -199,58 +154,6 @@ where | |||
| 199 | type Error = SpiDeviceError<BUS::Error, CS::Error>; | 154 | type Error = SpiDeviceError<BUS::Error, CS::Error>; |
| 200 | } | 155 | } |
| 201 | 156 | ||
| 202 | impl<BUS, M, CS> embedded_hal_1::spi::SpiDeviceRead for SpiDeviceWithConfig<'_, M, BUS, CS> | ||
| 203 | where | ||
| 204 | M: RawMutex, | ||
| 205 | BUS: SpiBusRead + SetConfig, | ||
| 206 | CS: OutputPin, | ||
| 207 | { | ||
| 208 | fn read_transaction(&mut self, operations: &mut [&mut [u8]]) -> Result<(), Self::Error> { | ||
| 209 | self.bus.lock(|bus| { | ||
| 210 | let mut bus = bus.borrow_mut(); | ||
| 211 | bus.set_config(&self.config); | ||
| 212 | self.cs.set_low().map_err(SpiDeviceError::Cs)?; | ||
| 213 | |||
| 214 | let op_res = operations.iter_mut().try_for_each(|buf| bus.read(buf)); | ||
| 215 | |||
| 216 | // On failure, it's important to still flush and deassert CS. | ||
| 217 | let flush_res = bus.flush(); | ||
| 218 | let cs_res = self.cs.set_high(); | ||
| 219 | |||
| 220 | let op_res = op_res.map_err(SpiDeviceError::Spi)?; | ||
| 221 | flush_res.map_err(SpiDeviceError::Spi)?; | ||
| 222 | cs_res.map_err(SpiDeviceError::Cs)?; | ||
| 223 | Ok(op_res) | ||
| 224 | }) | ||
| 225 | } | ||
| 226 | } | ||
| 227 | |||
| 228 | impl<BUS, M, CS> embedded_hal_1::spi::SpiDeviceWrite for SpiDeviceWithConfig<'_, M, BUS, CS> | ||
| 229 | where | ||
| 230 | M: RawMutex, | ||
| 231 | BUS: SpiBusWrite + SetConfig, | ||
| 232 | CS: OutputPin, | ||
| 233 | { | ||
| 234 | fn write_transaction(&mut self, operations: &[&[u8]]) -> Result<(), Self::Error> { | ||
| 235 | self.bus.lock(|bus| { | ||
| 236 | let mut bus = bus.borrow_mut(); | ||
| 237 | bus.set_config(&self.config); | ||
| 238 | self.cs.set_low().map_err(SpiDeviceError::Cs)?; | ||
| 239 | |||
| 240 | let op_res = operations.iter().try_for_each(|buf| bus.write(buf)); | ||
| 241 | |||
| 242 | // On failure, it's important to still flush and deassert CS. | ||
| 243 | let flush_res = bus.flush(); | ||
| 244 | let cs_res = self.cs.set_high(); | ||
| 245 | |||
| 246 | let op_res = op_res.map_err(SpiDeviceError::Spi)?; | ||
| 247 | flush_res.map_err(SpiDeviceError::Spi)?; | ||
| 248 | cs_res.map_err(SpiDeviceError::Cs)?; | ||
| 249 | Ok(op_res) | ||
| 250 | }) | ||
| 251 | } | ||
| 252 | } | ||
| 253 | |||
| 254 | impl<BUS, M, CS> embedded_hal_1::spi::SpiDevice for SpiDeviceWithConfig<'_, M, BUS, CS> | 157 | impl<BUS, M, CS> embedded_hal_1::spi::SpiDevice for SpiDeviceWithConfig<'_, M, BUS, CS> |
| 255 | where | 158 | where |
| 256 | M: RawMutex, | 159 | M: RawMutex, |
| @@ -268,6 +171,13 @@ where | |||
| 268 | Operation::Write(buf) => bus.write(buf), | 171 | Operation::Write(buf) => bus.write(buf), |
| 269 | Operation::Transfer(read, write) => bus.transfer(read, write), | 172 | Operation::Transfer(read, write) => bus.transfer(read, write), |
| 270 | Operation::TransferInPlace(buf) => bus.transfer_in_place(buf), | 173 | Operation::TransferInPlace(buf) => bus.transfer_in_place(buf), |
| 174 | #[cfg(not(feature = "time"))] | ||
| 175 | Operation::DelayUs(_) => Err(SpiDeviceError::DelayUsNotSupported), | ||
| 176 | #[cfg(feature = "time")] | ||
| 177 | Operation::DelayUs(us) => { | ||
| 178 | embassy_time::block_for(embassy_time::Duration::from_micros(*us as _)); | ||
| 179 | Ok(()) | ||
| 180 | } | ||
| 271 | }); | 181 | }); |
| 272 | 182 | ||
| 273 | // On failure, it's important to still flush and deassert CS. | 183 | // On failure, it's important to still flush and deassert CS. |
diff --git a/embassy-embedded-hal/src/shared_bus/mod.rs b/embassy-embedded-hal/src/shared_bus/mod.rs index 617d921e9..79a90bd52 100644 --- a/embassy-embedded-hal/src/shared_bus/mod.rs +++ b/embassy-embedded-hal/src/shared_bus/mod.rs | |||
| @@ -30,11 +30,14 @@ where | |||
| 30 | /// Error returned by SPI device implementations in this crate. | 30 | /// Error returned by SPI device implementations in this crate. |
| 31 | #[derive(Copy, Clone, Eq, PartialEq, Debug)] | 31 | #[derive(Copy, Clone, Eq, PartialEq, Debug)] |
| 32 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | 32 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] |
| 33 | #[non_exhaustive] | ||
| 33 | pub enum SpiDeviceError<BUS, CS> { | 34 | pub enum SpiDeviceError<BUS, CS> { |
| 34 | /// An operation on the inner SPI bus failed. | 35 | /// An operation on the inner SPI bus failed. |
| 35 | Spi(BUS), | 36 | Spi(BUS), |
| 36 | /// Setting the value of the Chip Select (CS) pin failed. | 37 | /// Setting the value of the Chip Select (CS) pin failed. |
| 37 | Cs(CS), | 38 | Cs(CS), |
| 39 | /// DelayUs operations are not supported when the `time` Cargo feature is not enabled. | ||
| 40 | DelayUsNotSupported, | ||
| 38 | } | 41 | } |
| 39 | 42 | ||
| 40 | impl<BUS, CS> spi::Error for SpiDeviceError<BUS, CS> | 43 | impl<BUS, CS> spi::Error for SpiDeviceError<BUS, CS> |
| @@ -46,6 +49,7 @@ where | |||
| 46 | match self { | 49 | match self { |
| 47 | Self::Spi(e) => e.kind(), | 50 | Self::Spi(e) => e.kind(), |
| 48 | Self::Cs(_) => spi::ErrorKind::Other, | 51 | Self::Cs(_) => spi::ErrorKind::Other, |
| 52 | Self::DelayUsNotSupported => spi::ErrorKind::Other, | ||
| 49 | } | 53 | } |
| 50 | } | 54 | } |
| 51 | } | 55 | } |
diff --git a/embassy-executor/Cargo.toml b/embassy-executor/Cargo.toml index 1e5494ef8..590718e3e 100644 --- a/embassy-executor/Cargo.toml +++ b/embassy-executor/Cargo.toml | |||
| @@ -61,8 +61,8 @@ log = { version = "0.4.14", optional = true } | |||
| 61 | rtos-trace = { version = "0.1.2", optional = true } | 61 | rtos-trace = { version = "0.1.2", optional = true } |
| 62 | 62 | ||
| 63 | futures-util = { version = "0.3.17", default-features = false } | 63 | futures-util = { version = "0.3.17", default-features = false } |
| 64 | embassy-macros = { version = "0.2.0", path = "../embassy-macros" } | 64 | embassy-macros = { version = "0.2.0", path = "../embassy-macros" } |
| 65 | embassy-time = { version = "0.1.0", path = "../embassy-time", optional = true} | 65 | embassy-time = { version = "0.1.2", path = "../embassy-time", optional = true} |
| 66 | atomic-polyfill = "1.0.1" | 66 | atomic-polyfill = "1.0.1" |
| 67 | critical-section = "1.1" | 67 | critical-section = "1.1" |
| 68 | static_cell = "1.1" | 68 | static_cell = "1.1" |
diff --git a/embassy-executor/src/raw/mod.rs b/embassy-executor/src/raw/mod.rs index bd0cff26b..f3760f589 100644 --- a/embassy-executor/src/raw/mod.rs +++ b/embassy-executor/src/raw/mod.rs | |||
| @@ -165,6 +165,9 @@ impl<F: Future + 'static> TaskStorage<F> { | |||
| 165 | Poll::Ready(_) => { | 165 | Poll::Ready(_) => { |
| 166 | this.future.drop_in_place(); | 166 | this.future.drop_in_place(); |
| 167 | this.raw.state.fetch_and(!STATE_SPAWNED, Ordering::AcqRel); | 167 | this.raw.state.fetch_and(!STATE_SPAWNED, Ordering::AcqRel); |
| 168 | |||
| 169 | #[cfg(feature = "integrated-timers")] | ||
| 170 | this.raw.expires_at.set(Instant::MAX); | ||
| 168 | } | 171 | } |
| 169 | Poll::Pending => {} | 172 | Poll::Pending => {} |
| 170 | } | 173 | } |
diff --git a/embassy-hal-common/src/peripheral.rs b/embassy-hal-common/src/peripheral.rs index c7133bac6..38b4c452e 100644 --- a/embassy-hal-common/src/peripheral.rs +++ b/embassy-hal-common/src/peripheral.rs | |||
| @@ -161,7 +161,7 @@ pub trait Peripheral: Sized { | |||
| 161 | } | 161 | } |
| 162 | } | 162 | } |
| 163 | 163 | ||
| 164 | impl<'b, T: Deref> Peripheral for T | 164 | impl<'b, T: DerefMut> Peripheral for T |
| 165 | where | 165 | where |
| 166 | T::Target: Peripheral, | 166 | T::Target: Peripheral, |
| 167 | { | 167 | { |
diff --git a/embassy-lora/Cargo.toml b/embassy-lora/Cargo.toml index 05b6fa2d0..e4524af5b 100644 --- a/embassy-lora/Cargo.toml +++ b/embassy-lora/Cargo.toml | |||
| @@ -20,11 +20,11 @@ defmt = ["dep:defmt", "lorawan-device/defmt"] | |||
| 20 | defmt = { version = "0.3", optional = true } | 20 | defmt = { version = "0.3", optional = true } |
| 21 | log = { version = "0.4.14", optional = true } | 21 | log = { version = "0.4.14", optional = true } |
| 22 | 22 | ||
| 23 | embassy-time = { version = "0.1.0", path = "../embassy-time" } | 23 | embassy-time = { version = "0.1.2", path = "../embassy-time" } |
| 24 | embassy-sync = { version = "0.2.0", path = "../embassy-sync" } | 24 | embassy-sync = { version = "0.2.0", path = "../embassy-sync" } |
| 25 | embassy-stm32 = { version = "0.1.0", path = "../embassy-stm32", default-features = false, optional = true } | 25 | embassy-stm32 = { version = "0.1.0", path = "../embassy-stm32", default-features = false, optional = true } |
| 26 | embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-alpha.10" } | 26 | embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-alpha.11" } |
| 27 | embedded-hal-async = { version = "=0.2.0-alpha.1" } | 27 | embedded-hal-async = { version = "=0.2.0-alpha.2" } |
| 28 | embassy-hal-common = { version = "0.1.0", path = "../embassy-hal-common", default-features = false } | 28 | embassy-hal-common = { version = "0.1.0", path = "../embassy-hal-common", default-features = false } |
| 29 | futures = { version = "0.3.17", default-features = false, features = [ "async-await" ] } | 29 | futures = { version = "0.3.17", default-features = false, features = [ "async-await" ] } |
| 30 | embedded-hal = { version = "0.2", features = ["unproven"] } | 30 | embedded-hal = { version = "0.2", features = ["unproven"] } |
| @@ -32,3 +32,6 @@ bit_field = { version = "0.10" } | |||
| 32 | 32 | ||
| 33 | lora-phy = { version = "1" } | 33 | lora-phy = { version = "1" } |
| 34 | lorawan-device = { version = "0.10.0", default-features = false, features = ["async"] } | 34 | lorawan-device = { version = "0.10.0", default-features = false, features = ["async"] } |
| 35 | |||
| 36 | [patch.crates-io] | ||
| 37 | lora-phy = { git = "https://github.com/embassy-rs/lora-phy", rev = "ad289428fd44b02788e2fa2116445cc8f640a265" } | ||
diff --git a/embassy-net-esp-hosted/Cargo.toml b/embassy-net-esp-hosted/Cargo.toml index a7e18ee09..26f5b40bd 100644 --- a/embassy-net-esp-hosted/Cargo.toml +++ b/embassy-net-esp-hosted/Cargo.toml | |||
| @@ -7,13 +7,13 @@ edition = "2021" | |||
| 7 | defmt = { version = "0.3", optional = true } | 7 | defmt = { version = "0.3", optional = true } |
| 8 | log = { version = "0.4.14", optional = true } | 8 | log = { version = "0.4.14", optional = true } |
| 9 | 9 | ||
| 10 | embassy-time = { version = "0.1.0", path = "../embassy-time" } | 10 | embassy-time = { version = "0.1.2", path = "../embassy-time" } |
| 11 | embassy-sync = { version = "0.2.0", path = "../embassy-sync"} | 11 | embassy-sync = { version = "0.2.0", path = "../embassy-sync"} |
| 12 | embassy-futures = { version = "0.1.0", path = "../embassy-futures"} | 12 | embassy-futures = { version = "0.1.0", path = "../embassy-futures"} |
| 13 | embassy-net-driver-channel = { version = "0.1.0", path = "../embassy-net-driver-channel"} | 13 | embassy-net-driver-channel = { version = "0.1.0", path = "../embassy-net-driver-channel"} |
| 14 | 14 | ||
| 15 | embedded-hal = { version = "1.0.0-alpha.10" } | 15 | embedded-hal = { version = "1.0.0-alpha.11" } |
| 16 | embedded-hal-async = { version = "=0.2.0-alpha.1" } | 16 | embedded-hal-async = { version = "=0.2.0-alpha.2" } |
| 17 | 17 | ||
| 18 | noproto = { git="https://github.com/embassy-rs/noproto", default-features = false, features = ["derive"] } | 18 | noproto = { git="https://github.com/embassy-rs/noproto", default-features = false, features = ["derive"] } |
| 19 | #noproto = { version = "0.1", path = "/home/dirbaio/noproto", default-features = false, features = ["derive"] } | 19 | #noproto = { version = "0.1", path = "/home/dirbaio/noproto", default-features = false, features = ["derive"] } |
diff --git a/embassy-net-esp-hosted/src/control.rs b/embassy-net-esp-hosted/src/control.rs index fce82ade7..79f8cde7b 100644 --- a/embassy-net-esp-hosted/src/control.rs +++ b/embassy-net-esp-hosted/src/control.rs | |||
| @@ -54,7 +54,9 @@ impl<'a> Control<'a> { | |||
| 54 | })), | 54 | })), |
| 55 | }; | 55 | }; |
| 56 | let resp = self.ioctl(req).await; | 56 | let resp = self.ioctl(req).await; |
| 57 | let proto::CtrlMsgPayload::RespConnectAp(resp) = resp.payload.unwrap() else { panic!("unexpected resp") }; | 57 | let proto::CtrlMsgPayload::RespConnectAp(resp) = resp.payload.unwrap() else { |
| 58 | panic!("unexpected resp") | ||
| 59 | }; | ||
| 58 | debug!("======= {:?}", Debug2Format(&resp)); | 60 | debug!("======= {:?}", Debug2Format(&resp)); |
| 59 | assert_eq!(resp.resp, 0); | 61 | assert_eq!(resp.resp, 0); |
| 60 | self.state_ch.set_link_state(LinkState::Up); | 62 | self.state_ch.set_link_state(LinkState::Up); |
| @@ -71,7 +73,9 @@ impl<'a> Control<'a> { | |||
| 71 | )), | 73 | )), |
| 72 | }; | 74 | }; |
| 73 | let resp = self.ioctl(req).await; | 75 | let resp = self.ioctl(req).await; |
| 74 | let proto::CtrlMsgPayload::RespGetMacAddress(resp) = resp.payload.unwrap() else { panic!("unexpected resp") }; | 76 | let proto::CtrlMsgPayload::RespGetMacAddress(resp) = resp.payload.unwrap() else { |
| 77 | panic!("unexpected resp") | ||
| 78 | }; | ||
| 75 | assert_eq!(resp.resp, 0); | 79 | assert_eq!(resp.resp, 0); |
| 76 | 80 | ||
| 77 | // WHY IS THIS A STRING? WHYYYY | 81 | // WHY IS THIS A STRING? WHYYYY |
| @@ -100,7 +104,9 @@ impl<'a> Control<'a> { | |||
| 100 | payload: Some(proto::CtrlMsgPayload::ReqSetWifiMode(proto::CtrlMsgReqSetMode { mode })), | 104 | payload: Some(proto::CtrlMsgPayload::ReqSetWifiMode(proto::CtrlMsgReqSetMode { mode })), |
| 101 | }; | 105 | }; |
| 102 | let resp = self.ioctl(req).await; | 106 | let resp = self.ioctl(req).await; |
| 103 | let proto::CtrlMsgPayload::RespSetWifiMode(resp) = resp.payload.unwrap() else { panic!("unexpected resp") }; | 107 | let proto::CtrlMsgPayload::RespSetWifiMode(resp) = resp.payload.unwrap() else { |
| 108 | panic!("unexpected resp") | ||
| 109 | }; | ||
| 104 | assert_eq!(resp.resp, 0); | 110 | assert_eq!(resp.resp, 0); |
| 105 | } | 111 | } |
| 106 | 112 | ||
diff --git a/embassy-net-esp-hosted/src/lib.rs b/embassy-net-esp-hosted/src/lib.rs index 44dfbe89c..a35adfca0 100644 --- a/embassy-net-esp-hosted/src/lib.rs +++ b/embassy-net-esp-hosted/src/lib.rs | |||
| @@ -311,14 +311,14 @@ where | |||
| 311 | fn handle_event(&self, data: &[u8]) { | 311 | fn handle_event(&self, data: &[u8]) { |
| 312 | let Ok(event) = noproto::read::<CtrlMsg>(data) else { | 312 | let Ok(event) = noproto::read::<CtrlMsg>(data) else { |
| 313 | warn!("failed to parse event"); | 313 | warn!("failed to parse event"); |
| 314 | return | 314 | return; |
| 315 | }; | 315 | }; |
| 316 | 316 | ||
| 317 | debug!("event: {:?}", &event); | 317 | debug!("event: {:?}", &event); |
| 318 | 318 | ||
| 319 | let Some(payload) = &event.payload else { | 319 | let Some(payload) = &event.payload else { |
| 320 | warn!("event without payload?"); | 320 | warn!("event without payload?"); |
| 321 | return | 321 | return; |
| 322 | }; | 322 | }; |
| 323 | 323 | ||
| 324 | match payload { | 324 | match payload { |
diff --git a/embassy-net-w5500/Cargo.toml b/embassy-net-w5500/Cargo.toml index 37d15c7ac..8972b814a 100644 --- a/embassy-net-w5500/Cargo.toml +++ b/embassy-net-w5500/Cargo.toml | |||
| @@ -8,11 +8,11 @@ license = "MIT OR Apache-2.0" | |||
| 8 | edition = "2021" | 8 | edition = "2021" |
| 9 | 9 | ||
| 10 | [dependencies] | 10 | [dependencies] |
| 11 | embedded-hal = { version = "1.0.0-alpha.10" } | 11 | embedded-hal = { version = "1.0.0-alpha.11" } |
| 12 | embedded-hal-async = { version = "=0.2.0-alpha.1" } | 12 | embedded-hal-async = { version = "=0.2.0-alpha.2" } |
| 13 | embassy-net-driver-channel = { version = "0.1.0", path = "../embassy-net-driver-channel"} | 13 | embassy-net-driver-channel = { version = "0.1.0", path = "../embassy-net-driver-channel" } |
| 14 | embassy-time = { version = "0.1.0" } | 14 | embassy-time = { version = "0.1.2", path = "../embassy-time" } |
| 15 | embassy-futures = { version = "0.1.0" } | 15 | embassy-futures = { version = "0.1.0", path = "../embassy-futures" } |
| 16 | defmt = { version = "0.3", optional = true } | 16 | defmt = { version = "0.3", optional = true } |
| 17 | 17 | ||
| 18 | [package.metadata.embassy_docs] | 18 | [package.metadata.embassy_docs] |
diff --git a/embassy-net-w5500/src/spi.rs b/embassy-net-w5500/src/spi.rs index 6cd52c44d..07749d6be 100644 --- a/embassy-net-w5500/src/spi.rs +++ b/embassy-net-w5500/src/spi.rs | |||
| @@ -22,7 +22,11 @@ impl<SPI: SpiDevice> SpiInterface<SPI> { | |||
| 22 | let address_phase = address.to_be_bytes(); | 22 | let address_phase = address.to_be_bytes(); |
| 23 | let control_phase = [(block as u8) << 3 | 0b0000_0100]; | 23 | let control_phase = [(block as u8) << 3 | 0b0000_0100]; |
| 24 | let data_phase = data; | 24 | let data_phase = data; |
| 25 | let operations = &[&address_phase[..], &control_phase, &data_phase]; | 25 | let operations = &mut [ |
| 26 | self.0.write_transaction(operations).await | 26 | Operation::Write(&address_phase[..]), |
| 27 | Operation::Write(&control_phase), | ||
| 28 | Operation::Write(&data_phase), | ||
| 29 | ]; | ||
| 30 | self.0.transaction(operations).await | ||
| 27 | } | 31 | } |
| 28 | } | 32 | } |
diff --git a/embassy-net/Cargo.toml b/embassy-net/Cargo.toml index e89039daa..6dc429ddc 100644 --- a/embassy-net/Cargo.toml +++ b/embassy-net/Cargo.toml | |||
| @@ -50,7 +50,7 @@ smoltcp = { version = "0.10.0", default-features = false, features = [ | |||
| 50 | ] } | 50 | ] } |
| 51 | 51 | ||
| 52 | embassy-net-driver = { version = "0.1.0", path = "../embassy-net-driver" } | 52 | embassy-net-driver = { version = "0.1.0", path = "../embassy-net-driver" } |
| 53 | embassy-time = { version = "0.1.0", path = "../embassy-time" } | 53 | embassy-time = { version = "0.1.2", path = "../embassy-time" } |
| 54 | embassy-sync = { version = "0.2.0", path = "../embassy-sync" } | 54 | embassy-sync = { version = "0.2.0", path = "../embassy-sync" } |
| 55 | embedded-io = { version = "0.4.0", optional = true } | 55 | embedded-io = { version = "0.4.0", optional = true } |
| 56 | 56 | ||
diff --git a/embassy-net/src/lib.rs b/embassy-net/src/lib.rs index 840d7a09a..0d0a986f6 100644 --- a/embassy-net/src/lib.rs +++ b/embassy-net/src/lib.rs | |||
| @@ -34,7 +34,7 @@ use smoltcp::socket::dhcpv4::{self, RetryConfig}; | |||
| 34 | pub use smoltcp::wire::IpListenEndpoint; | 34 | pub use smoltcp::wire::IpListenEndpoint; |
| 35 | #[cfg(feature = "medium-ethernet")] | 35 | #[cfg(feature = "medium-ethernet")] |
| 36 | pub use smoltcp::wire::{EthernetAddress, HardwareAddress}; | 36 | pub use smoltcp::wire::{EthernetAddress, HardwareAddress}; |
| 37 | pub use smoltcp::wire::{IpAddress, IpCidr}; | 37 | pub use smoltcp::wire::{IpAddress, IpCidr, IpEndpoint}; |
| 38 | #[cfg(feature = "proto-ipv4")] | 38 | #[cfg(feature = "proto-ipv4")] |
| 39 | pub use smoltcp::wire::{Ipv4Address, Ipv4Cidr}; | 39 | pub use smoltcp::wire::{Ipv4Address, Ipv4Cidr}; |
| 40 | #[cfg(feature = "proto-ipv6")] | 40 | #[cfg(feature = "proto-ipv6")] |
diff --git a/embassy-net/src/udp.rs b/embassy-net/src/udp.rs index 36f8d06f2..0d97b6db1 100644 --- a/embassy-net/src/udp.rs +++ b/embassy-net/src/udp.rs | |||
| @@ -3,7 +3,7 @@ | |||
| 3 | use core::cell::RefCell; | 3 | use core::cell::RefCell; |
| 4 | use core::future::poll_fn; | 4 | use core::future::poll_fn; |
| 5 | use core::mem; | 5 | use core::mem; |
| 6 | use core::task::Poll; | 6 | use core::task::{Context, Poll}; |
| 7 | 7 | ||
| 8 | use embassy_net_driver::Driver; | 8 | use embassy_net_driver::Driver; |
| 9 | use smoltcp::iface::{Interface, SocketHandle}; | 9 | use smoltcp::iface::{Interface, SocketHandle}; |
| @@ -102,37 +102,61 @@ impl<'a> UdpSocket<'a> { | |||
| 102 | /// | 102 | /// |
| 103 | /// Returns the number of bytes received and the remote endpoint. | 103 | /// Returns the number of bytes received and the remote endpoint. |
| 104 | pub async fn recv_from(&self, buf: &mut [u8]) -> Result<(usize, IpEndpoint), Error> { | 104 | pub async fn recv_from(&self, buf: &mut [u8]) -> Result<(usize, IpEndpoint), Error> { |
| 105 | poll_fn(move |cx| { | 105 | poll_fn(move |cx| self.poll_recv_from(buf, cx)).await |
| 106 | self.with_mut(|s, _| match s.recv_slice(buf) { | 106 | } |
| 107 | Ok((n, meta)) => Poll::Ready(Ok((n, meta.endpoint))), | 107 | |
| 108 | // No data ready | 108 | /// Receive a datagram. |
| 109 | Err(udp::RecvError::Exhausted) => { | 109 | /// |
| 110 | s.register_recv_waker(cx.waker()); | 110 | /// When no datagram is available, this method will return `Poll::Pending` and |
| 111 | Poll::Pending | 111 | /// register the current task to be notified when a datagram is received. |
| 112 | } | 112 | /// |
| 113 | }) | 113 | /// When a datagram is received, this method will return `Poll::Ready` with the |
| 114 | /// number of bytes received and the remote endpoint. | ||
| 115 | pub fn poll_recv_from(&self, buf: &mut [u8], cx: &mut Context<'_>) -> Poll<Result<(usize, IpEndpoint), Error>> { | ||
| 116 | self.with_mut(|s, _| match s.recv_slice(buf) { | ||
| 117 | Ok((n, meta)) => Poll::Ready(Ok((n, meta.endpoint))), | ||
| 118 | // No data ready | ||
| 119 | Err(udp::RecvError::Exhausted) => { | ||
| 120 | s.register_recv_waker(cx.waker()); | ||
| 121 | Poll::Pending | ||
| 122 | } | ||
| 114 | }) | 123 | }) |
| 115 | .await | ||
| 116 | } | 124 | } |
| 117 | 125 | ||
| 118 | /// Send a datagram to the specified remote endpoint. | 126 | /// Send a datagram to the specified remote endpoint. |
| 127 | /// | ||
| 128 | /// This method will wait until the datagram has been sent. | ||
| 129 | /// | ||
| 130 | /// When the remote endpoint is not reachable, this method will return `Err(Error::NoRoute)` | ||
| 119 | pub async fn send_to<T>(&self, buf: &[u8], remote_endpoint: T) -> Result<(), Error> | 131 | pub async fn send_to<T>(&self, buf: &[u8], remote_endpoint: T) -> Result<(), Error> |
| 120 | where | 132 | where |
| 121 | T: Into<IpEndpoint>, | 133 | T: Into<IpEndpoint>, |
| 122 | { | 134 | { |
| 123 | let remote_endpoint = remote_endpoint.into(); | 135 | let remote_endpoint: IpEndpoint = remote_endpoint.into(); |
| 124 | poll_fn(move |cx| { | 136 | poll_fn(move |cx| self.poll_send_to(buf, remote_endpoint, cx)).await |
| 125 | self.with_mut(|s, _| match s.send_slice(buf, remote_endpoint) { | 137 | } |
| 126 | // Entire datagram has been sent | 138 | |
| 127 | Ok(()) => Poll::Ready(Ok(())), | 139 | /// Send a datagram to the specified remote endpoint. |
| 128 | Err(udp::SendError::BufferFull) => { | 140 | /// |
| 129 | s.register_send_waker(cx.waker()); | 141 | /// When the datagram has been sent, this method will return `Poll::Ready(Ok())`. |
| 130 | Poll::Pending | 142 | /// |
| 131 | } | 143 | /// When the socket's send buffer is full, this method will return `Poll::Pending` |
| 132 | Err(udp::SendError::Unaddressable) => Poll::Ready(Err(Error::NoRoute)), | 144 | /// and register the current task to be notified when the buffer has space available. |
| 133 | }) | 145 | /// |
| 146 | /// When the remote endpoint is not reachable, this method will return `Poll::Ready(Err(Error::NoRoute))`. | ||
| 147 | pub fn poll_send_to<T>(&self, buf: &[u8], remote_endpoint: T, cx: &mut Context<'_>) -> Poll<Result<(), Error>> | ||
| 148 | where | ||
| 149 | T: Into<IpEndpoint>, | ||
| 150 | { | ||
| 151 | self.with_mut(|s, _| match s.send_slice(buf, remote_endpoint) { | ||
| 152 | // Entire datagram has been sent | ||
| 153 | Ok(()) => Poll::Ready(Ok(())), | ||
| 154 | Err(udp::SendError::BufferFull) => { | ||
| 155 | s.register_send_waker(cx.waker()); | ||
| 156 | Poll::Pending | ||
| 157 | } | ||
| 158 | Err(udp::SendError::Unaddressable) => Poll::Ready(Err(Error::NoRoute)), | ||
| 134 | }) | 159 | }) |
| 135 | .await | ||
| 136 | } | 160 | } |
| 137 | 161 | ||
| 138 | /// Returns the local endpoint of the socket. | 162 | /// Returns the local endpoint of the socket. |
diff --git a/embassy-nrf/Cargo.toml b/embassy-nrf/Cargo.toml index 3e858f854..57dd22f1c 100644 --- a/embassy-nrf/Cargo.toml +++ b/embassy-nrf/Cargo.toml | |||
| @@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0" | |||
| 8 | src_base = "https://github.com/embassy-rs/embassy/blob/embassy-nrf-v$VERSION/embassy-nrf/src/" | 8 | src_base = "https://github.com/embassy-rs/embassy/blob/embassy-nrf-v$VERSION/embassy-nrf/src/" |
| 9 | src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-nrf/src/" | 9 | src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-nrf/src/" |
| 10 | 10 | ||
| 11 | features = ["nightly", "defmt", "unstable-pac", "unstable-traits", "gpiote", "time-driver-rtc1"] | 11 | features = ["nightly", "time", "defmt", "unstable-pac", "unstable-traits", "gpiote", "time-driver-rtc1"] |
| 12 | flavors = [ | 12 | flavors = [ |
| 13 | { regex_feature = "nrf52.*", target = "thumbv7em-none-eabihf" }, | 13 | { regex_feature = "nrf52.*", target = "thumbv7em-none-eabihf" }, |
| 14 | { regex_feature = "nrf53.*", target = "thumbv8m.main-none-eabihf" }, | 14 | { regex_feature = "nrf53.*", target = "thumbv8m.main-none-eabihf" }, |
| @@ -91,22 +91,22 @@ _dppi = [] | |||
| 91 | _gpio-p1 = [] | 91 | _gpio-p1 = [] |
| 92 | 92 | ||
| 93 | [dependencies] | 93 | [dependencies] |
| 94 | embassy-time = { version = "0.1.0", path = "../embassy-time", optional = true } | 94 | embassy-time = { version = "0.1.2", path = "../embassy-time", optional = true } |
| 95 | embassy-sync = { version = "0.2.0", path = "../embassy-sync" } | 95 | embassy-sync = { version = "0.2.0", path = "../embassy-sync" } |
| 96 | embassy-hal-common = {version = "0.1.0", path = "../embassy-hal-common", features = ["cortex-m", "prio-bits-3"] } | 96 | embassy-hal-common = {version = "0.1.0", path = "../embassy-hal-common", features = ["cortex-m", "prio-bits-3"] } |
| 97 | embassy-embedded-hal = {version = "0.1.0", path = "../embassy-embedded-hal" } | 97 | embassy-embedded-hal = {version = "0.1.0", path = "../embassy-embedded-hal" } |
| 98 | embassy-usb-driver = {version = "0.1.0", path = "../embassy-usb-driver", optional=true } | 98 | embassy-usb-driver = {version = "0.1.0", path = "../embassy-usb-driver", optional=true } |
| 99 | 99 | ||
| 100 | embedded-hal-02 = { package = "embedded-hal", version = "0.2.6", features = ["unproven"] } | 100 | embedded-hal-02 = { package = "embedded-hal", version = "0.2.6", features = ["unproven"] } |
| 101 | embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-alpha.10", optional = true} | 101 | embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-alpha.11", optional = true} |
| 102 | embedded-hal-async = { version = "=0.2.0-alpha.1", optional = true} | 102 | embedded-hal-async = { version = "=0.2.0-alpha.2", optional = true} |
| 103 | embedded-io = { version = "0.4.0", features = ["async"], optional = true } | 103 | embedded-io = { version = "0.4.0", features = ["async"], optional = true } |
| 104 | 104 | ||
| 105 | defmt = { version = "0.3", optional = true } | 105 | defmt = { version = "0.3", optional = true } |
| 106 | log = { version = "0.4.14", optional = true } | 106 | log = { version = "0.4.14", optional = true } |
| 107 | cortex-m-rt = ">=0.6.15,<0.8" | 107 | cortex-m-rt = ">=0.6.15,<0.8" |
| 108 | cortex-m = "0.7.6" | 108 | cortex-m = "0.7.6" |
| 109 | futures = { version = "0.3.17", default-features = false } | 109 | futures = { version = "0.3.17", default-features = false } |
| 110 | critical-section = "1.1" | 110 | critical-section = "1.1" |
| 111 | rand_core = "0.6.3" | 111 | rand_core = "0.6.3" |
| 112 | fixed = "1.10.0" | 112 | fixed = "1.10.0" |
| @@ -114,13 +114,13 @@ embedded-storage = "0.3.0" | |||
| 114 | embedded-storage-async = { version = "0.4.0", optional = true } | 114 | embedded-storage-async = { version = "0.4.0", optional = true } |
| 115 | cfg-if = "1.0.0" | 115 | cfg-if = "1.0.0" |
| 116 | 116 | ||
| 117 | nrf52805-pac = { version = "0.12.0", optional = true } | 117 | nrf52805-pac = { version = "0.12.0", optional = true } |
| 118 | nrf52810-pac = { version = "0.12.0", optional = true } | 118 | nrf52810-pac = { version = "0.12.0", optional = true } |
| 119 | nrf52811-pac = { version = "0.12.0", optional = true } | 119 | nrf52811-pac = { version = "0.12.0", optional = true } |
| 120 | nrf52820-pac = { version = "0.12.0", optional = true } | 120 | nrf52820-pac = { version = "0.12.0", optional = true } |
| 121 | nrf52832-pac = { version = "0.12.0", optional = true } | 121 | nrf52832-pac = { version = "0.12.0", optional = true } |
| 122 | nrf52833-pac = { version = "0.12.0", optional = true } | 122 | nrf52833-pac = { version = "0.12.0", optional = true } |
| 123 | nrf52840-pac = { version = "0.12.0", optional = true } | 123 | nrf52840-pac = { version = "0.12.0", optional = true } |
| 124 | nrf5340-app-pac = { version = "0.12.0", optional = true } | 124 | nrf5340-app-pac = { version = "0.12.0", optional = true } |
| 125 | nrf5340-net-pac = { version = "0.12.0", optional = true } | 125 | nrf5340-net-pac = { version = "0.12.0", optional = true } |
| 126 | nrf9160-pac = { version = "0.12.0", optional = true } | 126 | nrf9160-pac = { version = "0.12.0", optional = true } |
diff --git a/embassy-nrf/src/gpiote.rs b/embassy-nrf/src/gpiote.rs index 21d0d9564..6550f2abd 100644 --- a/embassy-nrf/src/gpiote.rs +++ b/embassy-nrf/src/gpiote.rs | |||
| @@ -221,7 +221,7 @@ impl<'d, C: Channel, T: GpioPin> InputChannel<'d, C, T> { | |||
| 221 | } | 221 | } |
| 222 | 222 | ||
| 223 | /// Returns the IN event, for use with PPI. | 223 | /// Returns the IN event, for use with PPI. |
| 224 | pub fn event_in(&self) -> Event { | 224 | pub fn event_in(&self) -> Event<'d> { |
| 225 | let g = regs(); | 225 | let g = regs(); |
| 226 | Event::from_reg(&g.events_in[self.ch.number()]) | 226 | Event::from_reg(&g.events_in[self.ch.number()]) |
| 227 | } | 227 | } |
| @@ -292,21 +292,21 @@ impl<'d, C: Channel, T: GpioPin> OutputChannel<'d, C, T> { | |||
| 292 | } | 292 | } |
| 293 | 293 | ||
| 294 | /// Returns the OUT task, for use with PPI. | 294 | /// Returns the OUT task, for use with PPI. |
| 295 | pub fn task_out(&self) -> Task { | 295 | pub fn task_out(&self) -> Task<'d> { |
| 296 | let g = regs(); | 296 | let g = regs(); |
| 297 | Task::from_reg(&g.tasks_out[self.ch.number()]) | 297 | Task::from_reg(&g.tasks_out[self.ch.number()]) |
| 298 | } | 298 | } |
| 299 | 299 | ||
| 300 | /// Returns the CLR task, for use with PPI. | 300 | /// Returns the CLR task, for use with PPI. |
| 301 | #[cfg(not(feature = "nrf51"))] | 301 | #[cfg(not(feature = "nrf51"))] |
| 302 | pub fn task_clr(&self) -> Task { | 302 | pub fn task_clr(&self) -> Task<'d> { |
| 303 | let g = regs(); | 303 | let g = regs(); |
| 304 | Task::from_reg(&g.tasks_clr[self.ch.number()]) | 304 | Task::from_reg(&g.tasks_clr[self.ch.number()]) |
| 305 | } | 305 | } |
| 306 | 306 | ||
| 307 | /// Returns the SET task, for use with PPI. | 307 | /// Returns the SET task, for use with PPI. |
| 308 | #[cfg(not(feature = "nrf51"))] | 308 | #[cfg(not(feature = "nrf51"))] |
| 309 | pub fn task_set(&self) -> Task { | 309 | pub fn task_set(&self) -> Task<'d> { |
| 310 | let g = regs(); | 310 | let g = regs(); |
| 311 | Task::from_reg(&g.tasks_set[self.ch.number()]) | 311 | Task::from_reg(&g.tasks_set[self.ch.number()]) |
| 312 | } | 312 | } |
diff --git a/embassy-nrf/src/ppi/dppi.rs b/embassy-nrf/src/ppi/dppi.rs index 3a1e7f170..40ccb2f09 100644 --- a/embassy-nrf/src/ppi/dppi.rs +++ b/embassy-nrf/src/ppi/dppi.rs | |||
| @@ -12,14 +12,14 @@ pub(crate) fn regs() -> &'static pac::dppic::RegisterBlock { | |||
| 12 | 12 | ||
| 13 | impl<'d, C: ConfigurableChannel> Ppi<'d, C, 1, 1> { | 13 | impl<'d, C: ConfigurableChannel> Ppi<'d, C, 1, 1> { |
| 14 | /// Configure PPI channel to trigger `task` on `event`. | 14 | /// Configure PPI channel to trigger `task` on `event`. |
| 15 | pub fn new_one_to_one(ch: impl Peripheral<P = C> + 'd, event: Event, task: Task) -> Self { | 15 | pub fn new_one_to_one(ch: impl Peripheral<P = C> + 'd, event: Event<'d>, task: Task<'d>) -> Self { |
| 16 | Ppi::new_many_to_many(ch, [event], [task]) | 16 | Ppi::new_many_to_many(ch, [event], [task]) |
| 17 | } | 17 | } |
| 18 | } | 18 | } |
| 19 | 19 | ||
| 20 | impl<'d, C: ConfigurableChannel> Ppi<'d, C, 1, 2> { | 20 | impl<'d, C: ConfigurableChannel> Ppi<'d, C, 1, 2> { |
| 21 | /// Configure PPI channel to trigger both `task1` and `task2` on `event`. | 21 | /// Configure PPI channel to trigger both `task1` and `task2` on `event`. |
| 22 | pub fn new_one_to_two(ch: impl Peripheral<P = C> + 'd, event: Event, task1: Task, task2: Task) -> Self { | 22 | pub fn new_one_to_two(ch: impl Peripheral<P = C> + 'd, event: Event<'d>, task1: Task<'d>, task2: Task<'d>) -> Self { |
| 23 | Ppi::new_many_to_many(ch, [event], [task1, task2]) | 23 | Ppi::new_many_to_many(ch, [event], [task1, task2]) |
| 24 | } | 24 | } |
| 25 | } | 25 | } |
| @@ -30,8 +30,8 @@ impl<'d, C: ConfigurableChannel, const EVENT_COUNT: usize, const TASK_COUNT: usi | |||
| 30 | /// Configure a DPPI channel to trigger all `tasks` when any of the `events` fires. | 30 | /// Configure a DPPI channel to trigger all `tasks` when any of the `events` fires. |
| 31 | pub fn new_many_to_many( | 31 | pub fn new_many_to_many( |
| 32 | ch: impl Peripheral<P = C> + 'd, | 32 | ch: impl Peripheral<P = C> + 'd, |
| 33 | events: [Event; EVENT_COUNT], | 33 | events: [Event<'d>; EVENT_COUNT], |
| 34 | tasks: [Task; TASK_COUNT], | 34 | tasks: [Task<'d>; TASK_COUNT], |
| 35 | ) -> Self { | 35 | ) -> Self { |
| 36 | into_ref!(ch); | 36 | into_ref!(ch); |
| 37 | 37 | ||
diff --git a/embassy-nrf/src/ppi/mod.rs b/embassy-nrf/src/ppi/mod.rs index 76757a248..ff6593bd5 100644 --- a/embassy-nrf/src/ppi/mod.rs +++ b/embassy-nrf/src/ppi/mod.rs | |||
| @@ -15,6 +15,7 @@ | |||
| 15 | //! many tasks and events, but any single task or event can only be coupled with one channel. | 15 | //! many tasks and events, but any single task or event can only be coupled with one channel. |
| 16 | //! | 16 | //! |
| 17 | 17 | ||
| 18 | use core::marker::PhantomData; | ||
| 18 | use core::ptr::NonNull; | 19 | use core::ptr::NonNull; |
| 19 | 20 | ||
| 20 | use embassy_hal_common::{impl_peripheral, into_ref, PeripheralRef}; | 21 | use embassy_hal_common::{impl_peripheral, into_ref, PeripheralRef}; |
| @@ -30,9 +31,9 @@ pub(crate) use _version::*; | |||
| 30 | pub struct Ppi<'d, C: Channel, const EVENT_COUNT: usize, const TASK_COUNT: usize> { | 31 | pub struct Ppi<'d, C: Channel, const EVENT_COUNT: usize, const TASK_COUNT: usize> { |
| 31 | ch: PeripheralRef<'d, C>, | 32 | ch: PeripheralRef<'d, C>, |
| 32 | #[cfg(feature = "_dppi")] | 33 | #[cfg(feature = "_dppi")] |
| 33 | events: [Event; EVENT_COUNT], | 34 | events: [Event<'d>; EVENT_COUNT], |
| 34 | #[cfg(feature = "_dppi")] | 35 | #[cfg(feature = "_dppi")] |
| 35 | tasks: [Task; TASK_COUNT], | 36 | tasks: [Task<'d>; TASK_COUNT], |
| 36 | } | 37 | } |
| 37 | 38 | ||
| 38 | /// PPI channel group driver. | 39 | /// PPI channel group driver. |
| @@ -95,7 +96,7 @@ impl<'d, G: Group> PpiGroup<'d, G> { | |||
| 95 | /// Get a reference to the "enable all" task. | 96 | /// Get a reference to the "enable all" task. |
| 96 | /// | 97 | /// |
| 97 | /// When triggered, it will enable all the channels in this group. | 98 | /// When triggered, it will enable all the channels in this group. |
| 98 | pub fn task_enable_all(&self) -> Task { | 99 | pub fn task_enable_all(&self) -> Task<'d> { |
| 99 | let n = self.g.number(); | 100 | let n = self.g.number(); |
| 100 | Task::from_reg(®s().tasks_chg[n].en) | 101 | Task::from_reg(®s().tasks_chg[n].en) |
| 101 | } | 102 | } |
| @@ -103,7 +104,7 @@ impl<'d, G: Group> PpiGroup<'d, G> { | |||
| 103 | /// Get a reference to the "disable all" task. | 104 | /// Get a reference to the "disable all" task. |
| 104 | /// | 105 | /// |
| 105 | /// When triggered, it will disable all the channels in this group. | 106 | /// When triggered, it will disable all the channels in this group. |
| 106 | pub fn task_disable_all(&self) -> Task { | 107 | pub fn task_disable_all(&self) -> Task<'d> { |
| 107 | let n = self.g.number(); | 108 | let n = self.g.number(); |
| 108 | Task::from_reg(®s().tasks_chg[n].dis) | 109 | Task::from_reg(®s().tasks_chg[n].dis) |
| 109 | } | 110 | } |
| @@ -125,16 +126,16 @@ const REGISTER_DPPI_CONFIG_OFFSET: usize = 0x80 / core::mem::size_of::<u32>(); | |||
| 125 | /// When a task is subscribed to a PPI channel, it will run when the channel is triggered by | 126 | /// When a task is subscribed to a PPI channel, it will run when the channel is triggered by |
| 126 | /// a published event. | 127 | /// a published event. |
| 127 | #[derive(PartialEq, Eq, Clone, Copy)] | 128 | #[derive(PartialEq, Eq, Clone, Copy)] |
| 128 | pub struct Task(NonNull<u32>); | 129 | pub struct Task<'d>(NonNull<u32>, PhantomData<&'d ()>); |
| 129 | 130 | ||
| 130 | impl Task { | 131 | impl<'d> Task<'d> { |
| 131 | /// Create a new `Task` from a task register pointer | 132 | /// Create a new `Task` from a task register pointer |
| 132 | /// | 133 | /// |
| 133 | /// # Safety | 134 | /// # Safety |
| 134 | /// | 135 | /// |
| 135 | /// `ptr` must be a pointer to a valid `TASKS_*` register from an nRF peripheral. | 136 | /// `ptr` must be a pointer to a valid `TASKS_*` register from an nRF peripheral. |
| 136 | pub unsafe fn new_unchecked(ptr: NonNull<u32>) -> Self { | 137 | pub unsafe fn new_unchecked(ptr: NonNull<u32>) -> Self { |
| 137 | Self(ptr) | 138 | Self(ptr, PhantomData) |
| 138 | } | 139 | } |
| 139 | 140 | ||
| 140 | /// Triggers this task. | 141 | /// Triggers this task. |
| @@ -143,7 +144,10 @@ impl Task { | |||
| 143 | } | 144 | } |
| 144 | 145 | ||
| 145 | pub(crate) fn from_reg<T>(reg: &T) -> Self { | 146 | pub(crate) fn from_reg<T>(reg: &T) -> Self { |
| 146 | Self(unsafe { NonNull::new_unchecked(reg as *const _ as *mut _) }) | 147 | Self( |
| 148 | unsafe { NonNull::new_unchecked(reg as *const _ as *mut _) }, | ||
| 149 | PhantomData, | ||
| 150 | ) | ||
| 147 | } | 151 | } |
| 148 | 152 | ||
| 149 | /// Address of subscription register for this task. | 153 | /// Address of subscription register for this task. |
| @@ -156,26 +160,29 @@ impl Task { | |||
| 156 | /// # Safety | 160 | /// # Safety |
| 157 | /// | 161 | /// |
| 158 | /// NonNull is not send, but this event is only allowed to point at registers and those exist in any context on the same core. | 162 | /// NonNull is not send, but this event is only allowed to point at registers and those exist in any context on the same core. |
| 159 | unsafe impl Send for Task {} | 163 | unsafe impl Send for Task<'_> {} |
| 160 | 164 | ||
| 161 | /// Represents an event that a peripheral can publish. | 165 | /// Represents an event that a peripheral can publish. |
| 162 | /// | 166 | /// |
| 163 | /// An event can be set to publish on a PPI channel when the event happens. | 167 | /// An event can be set to publish on a PPI channel when the event happens. |
| 164 | #[derive(PartialEq, Eq, Clone, Copy)] | 168 | #[derive(PartialEq, Eq, Clone, Copy)] |
| 165 | pub struct Event(NonNull<u32>); | 169 | pub struct Event<'d>(NonNull<u32>, PhantomData<&'d ()>); |
| 166 | 170 | ||
| 167 | impl Event { | 171 | impl<'d> Event<'d> { |
| 168 | /// Create a new `Event` from an event register pointer | 172 | /// Create a new `Event` from an event register pointer |
| 169 | /// | 173 | /// |
| 170 | /// # Safety | 174 | /// # Safety |
| 171 | /// | 175 | /// |
| 172 | /// `ptr` must be a pointer to a valid `EVENTS_*` register from an nRF peripheral. | 176 | /// `ptr` must be a pointer to a valid `EVENTS_*` register from an nRF peripheral. |
| 173 | pub unsafe fn new_unchecked(ptr: NonNull<u32>) -> Self { | 177 | pub unsafe fn new_unchecked(ptr: NonNull<u32>) -> Self { |
| 174 | Self(ptr) | 178 | Self(ptr, PhantomData) |
| 175 | } | 179 | } |
| 176 | 180 | ||
| 177 | pub(crate) fn from_reg<T>(reg: &T) -> Self { | 181 | pub(crate) fn from_reg<T>(reg: &'d T) -> Self { |
| 178 | Self(unsafe { NonNull::new_unchecked(reg as *const _ as *mut _) }) | 182 | Self( |
| 183 | unsafe { NonNull::new_unchecked(reg as *const _ as *mut _) }, | ||
| 184 | PhantomData, | ||
| 185 | ) | ||
| 179 | } | 186 | } |
| 180 | 187 | ||
| 181 | /// Describes whether this Event is currently in a triggered state. | 188 | /// Describes whether this Event is currently in a triggered state. |
| @@ -198,7 +205,7 @@ impl Event { | |||
| 198 | /// # Safety | 205 | /// # Safety |
| 199 | /// | 206 | /// |
| 200 | /// NonNull is not send, but this event is only allowed to point at registers and those exist in any context on the same core. | 207 | /// NonNull is not send, but this event is only allowed to point at registers and those exist in any context on the same core. |
| 201 | unsafe impl Send for Event {} | 208 | unsafe impl Send for Event<'_> {} |
| 202 | 209 | ||
| 203 | // ====================== | 210 | // ====================== |
| 204 | // traits | 211 | // traits |
diff --git a/embassy-nrf/src/ppi/ppi.rs b/embassy-nrf/src/ppi/ppi.rs index f1eeaee1e..1fe898625 100644 --- a/embassy-nrf/src/ppi/ppi.rs +++ b/embassy-nrf/src/ppi/ppi.rs | |||
| @@ -3,12 +3,12 @@ use embassy_hal_common::into_ref; | |||
| 3 | use super::{Channel, ConfigurableChannel, Event, Ppi, StaticChannel, Task}; | 3 | use super::{Channel, ConfigurableChannel, Event, Ppi, StaticChannel, Task}; |
| 4 | use crate::{pac, Peripheral}; | 4 | use crate::{pac, Peripheral}; |
| 5 | 5 | ||
| 6 | impl Task { | 6 | impl<'d> Task<'d> { |
| 7 | fn reg_val(&self) -> u32 { | 7 | fn reg_val(&self) -> u32 { |
| 8 | self.0.as_ptr() as _ | 8 | self.0.as_ptr() as _ |
| 9 | } | 9 | } |
| 10 | } | 10 | } |
| 11 | impl Event { | 11 | impl<'d> Event<'d> { |
| 12 | fn reg_val(&self) -> u32 { | 12 | fn reg_val(&self) -> u32 { |
| 13 | self.0.as_ptr() as _ | 13 | self.0.as_ptr() as _ |
| 14 | } | 14 | } |
| @@ -34,7 +34,7 @@ impl<'d, C: StaticChannel> Ppi<'d, C, 0, 1> { | |||
| 34 | 34 | ||
| 35 | impl<'d, C: ConfigurableChannel> Ppi<'d, C, 1, 1> { | 35 | impl<'d, C: ConfigurableChannel> Ppi<'d, C, 1, 1> { |
| 36 | /// Configure PPI channel to trigger `task` on `event`. | 36 | /// Configure PPI channel to trigger `task` on `event`. |
| 37 | pub fn new_one_to_one(ch: impl Peripheral<P = C> + 'd, event: Event, task: Task) -> Self { | 37 | pub fn new_one_to_one(ch: impl Peripheral<P = C> + 'd, event: Event<'d>, task: Task<'d>) -> Self { |
| 38 | into_ref!(ch); | 38 | into_ref!(ch); |
| 39 | 39 | ||
| 40 | let r = regs(); | 40 | let r = regs(); |
| @@ -49,7 +49,7 @@ impl<'d, C: ConfigurableChannel> Ppi<'d, C, 1, 1> { | |||
| 49 | #[cfg(not(feature = "nrf51"))] // Not for nrf51 because of the fork task | 49 | #[cfg(not(feature = "nrf51"))] // Not for nrf51 because of the fork task |
| 50 | impl<'d, C: ConfigurableChannel> Ppi<'d, C, 1, 2> { | 50 | impl<'d, C: ConfigurableChannel> Ppi<'d, C, 1, 2> { |
| 51 | /// Configure PPI channel to trigger both `task1` and `task2` on `event`. | 51 | /// Configure PPI channel to trigger both `task1` and `task2` on `event`. |
| 52 | pub fn new_one_to_two(ch: impl Peripheral<P = C> + 'd, event: Event, task1: Task, task2: Task) -> Self { | 52 | pub fn new_one_to_two(ch: impl Peripheral<P = C> + 'd, event: Event<'d>, task1: Task<'d>, task2: Task<'d>) -> Self { |
| 53 | into_ref!(ch); | 53 | into_ref!(ch); |
| 54 | 54 | ||
| 55 | let r = regs(); | 55 | let r = regs(); |
diff --git a/embassy-nrf/src/pwm.rs b/embassy-nrf/src/pwm.rs index 363a255d5..c8c81fa01 100644 --- a/embassy-nrf/src/pwm.rs +++ b/embassy-nrf/src/pwm.rs | |||
| @@ -181,7 +181,7 @@ impl<'d, T: Instance> SequencePwm<'d, T> { | |||
| 181 | 181 | ||
| 182 | /// Returns reference to `Stopped` event endpoint for PPI. | 182 | /// Returns reference to `Stopped` event endpoint for PPI. |
| 183 | #[inline(always)] | 183 | #[inline(always)] |
| 184 | pub fn event_stopped(&self) -> Event { | 184 | pub fn event_stopped(&self) -> Event<'d> { |
| 185 | let r = T::regs(); | 185 | let r = T::regs(); |
| 186 | 186 | ||
| 187 | Event::from_reg(&r.events_stopped) | 187 | Event::from_reg(&r.events_stopped) |
| @@ -189,7 +189,7 @@ impl<'d, T: Instance> SequencePwm<'d, T> { | |||
| 189 | 189 | ||
| 190 | /// Returns reference to `LoopsDone` event endpoint for PPI. | 190 | /// Returns reference to `LoopsDone` event endpoint for PPI. |
| 191 | #[inline(always)] | 191 | #[inline(always)] |
| 192 | pub fn event_loops_done(&self) -> Event { | 192 | pub fn event_loops_done(&self) -> Event<'d> { |
| 193 | let r = T::regs(); | 193 | let r = T::regs(); |
| 194 | 194 | ||
| 195 | Event::from_reg(&r.events_loopsdone) | 195 | Event::from_reg(&r.events_loopsdone) |
| @@ -197,7 +197,7 @@ impl<'d, T: Instance> SequencePwm<'d, T> { | |||
| 197 | 197 | ||
| 198 | /// Returns reference to `PwmPeriodEnd` event endpoint for PPI. | 198 | /// Returns reference to `PwmPeriodEnd` event endpoint for PPI. |
| 199 | #[inline(always)] | 199 | #[inline(always)] |
| 200 | pub fn event_pwm_period_end(&self) -> Event { | 200 | pub fn event_pwm_period_end(&self) -> Event<'d> { |
| 201 | let r = T::regs(); | 201 | let r = T::regs(); |
| 202 | 202 | ||
| 203 | Event::from_reg(&r.events_pwmperiodend) | 203 | Event::from_reg(&r.events_pwmperiodend) |
| @@ -205,7 +205,7 @@ impl<'d, T: Instance> SequencePwm<'d, T> { | |||
| 205 | 205 | ||
| 206 | /// Returns reference to `Seq0 End` event endpoint for PPI. | 206 | /// Returns reference to `Seq0 End` event endpoint for PPI. |
| 207 | #[inline(always)] | 207 | #[inline(always)] |
| 208 | pub fn event_seq_end(&self) -> Event { | 208 | pub fn event_seq_end(&self) -> Event<'d> { |
| 209 | let r = T::regs(); | 209 | let r = T::regs(); |
| 210 | 210 | ||
| 211 | Event::from_reg(&r.events_seqend[0]) | 211 | Event::from_reg(&r.events_seqend[0]) |
| @@ -213,7 +213,7 @@ impl<'d, T: Instance> SequencePwm<'d, T> { | |||
| 213 | 213 | ||
| 214 | /// Returns reference to `Seq1 End` event endpoint for PPI. | 214 | /// Returns reference to `Seq1 End` event endpoint for PPI. |
| 215 | #[inline(always)] | 215 | #[inline(always)] |
| 216 | pub fn event_seq1_end(&self) -> Event { | 216 | pub fn event_seq1_end(&self) -> Event<'d> { |
| 217 | let r = T::regs(); | 217 | let r = T::regs(); |
| 218 | 218 | ||
| 219 | Event::from_reg(&r.events_seqend[1]) | 219 | Event::from_reg(&r.events_seqend[1]) |
| @@ -221,7 +221,7 @@ impl<'d, T: Instance> SequencePwm<'d, T> { | |||
| 221 | 221 | ||
| 222 | /// Returns reference to `Seq0 Started` event endpoint for PPI. | 222 | /// Returns reference to `Seq0 Started` event endpoint for PPI. |
| 223 | #[inline(always)] | 223 | #[inline(always)] |
| 224 | pub fn event_seq0_started(&self) -> Event { | 224 | pub fn event_seq0_started(&self) -> Event<'d> { |
| 225 | let r = T::regs(); | 225 | let r = T::regs(); |
| 226 | 226 | ||
| 227 | Event::from_reg(&r.events_seqstarted[0]) | 227 | Event::from_reg(&r.events_seqstarted[0]) |
| @@ -229,7 +229,7 @@ impl<'d, T: Instance> SequencePwm<'d, T> { | |||
| 229 | 229 | ||
| 230 | /// Returns reference to `Seq1 Started` event endpoint for PPI. | 230 | /// Returns reference to `Seq1 Started` event endpoint for PPI. |
| 231 | #[inline(always)] | 231 | #[inline(always)] |
| 232 | pub fn event_seq1_started(&self) -> Event { | 232 | pub fn event_seq1_started(&self) -> Event<'d> { |
| 233 | let r = T::regs(); | 233 | let r = T::regs(); |
| 234 | 234 | ||
| 235 | Event::from_reg(&r.events_seqstarted[1]) | 235 | Event::from_reg(&r.events_seqstarted[1]) |
| @@ -240,7 +240,7 @@ impl<'d, T: Instance> SequencePwm<'d, T> { | |||
| 240 | /// | 240 | /// |
| 241 | /// Interacting with the sequence while it runs puts it in an unknown state | 241 | /// Interacting with the sequence while it runs puts it in an unknown state |
| 242 | #[inline(always)] | 242 | #[inline(always)] |
| 243 | pub unsafe fn task_start_seq0(&self) -> Task { | 243 | pub unsafe fn task_start_seq0(&self) -> Task<'d> { |
| 244 | let r = T::regs(); | 244 | let r = T::regs(); |
| 245 | 245 | ||
| 246 | Task::from_reg(&r.tasks_seqstart[0]) | 246 | Task::from_reg(&r.tasks_seqstart[0]) |
| @@ -251,7 +251,7 @@ impl<'d, T: Instance> SequencePwm<'d, T> { | |||
| 251 | /// | 251 | /// |
| 252 | /// Interacting with the sequence while it runs puts it in an unknown state | 252 | /// Interacting with the sequence while it runs puts it in an unknown state |
| 253 | #[inline(always)] | 253 | #[inline(always)] |
| 254 | pub unsafe fn task_start_seq1(&self) -> Task { | 254 | pub unsafe fn task_start_seq1(&self) -> Task<'d> { |
| 255 | let r = T::regs(); | 255 | let r = T::regs(); |
| 256 | 256 | ||
| 257 | Task::from_reg(&r.tasks_seqstart[1]) | 257 | Task::from_reg(&r.tasks_seqstart[1]) |
| @@ -262,7 +262,7 @@ impl<'d, T: Instance> SequencePwm<'d, T> { | |||
| 262 | /// | 262 | /// |
| 263 | /// Interacting with the sequence while it runs puts it in an unknown state | 263 | /// Interacting with the sequence while it runs puts it in an unknown state |
| 264 | #[inline(always)] | 264 | #[inline(always)] |
| 265 | pub unsafe fn task_next_step(&self) -> Task { | 265 | pub unsafe fn task_next_step(&self) -> Task<'d> { |
| 266 | let r = T::regs(); | 266 | let r = T::regs(); |
| 267 | 267 | ||
| 268 | Task::from_reg(&r.tasks_nextstep) | 268 | Task::from_reg(&r.tasks_nextstep) |
| @@ -273,7 +273,7 @@ impl<'d, T: Instance> SequencePwm<'d, T> { | |||
| 273 | /// | 273 | /// |
| 274 | /// Interacting with the sequence while it runs puts it in an unknown state | 274 | /// Interacting with the sequence while it runs puts it in an unknown state |
| 275 | #[inline(always)] | 275 | #[inline(always)] |
| 276 | pub unsafe fn task_stop(&self) -> Task { | 276 | pub unsafe fn task_stop(&self) -> Task<'d> { |
| 277 | let r = T::regs(); | 277 | let r = T::regs(); |
| 278 | 278 | ||
| 279 | Task::from_reg(&r.tasks_stop) | 279 | Task::from_reg(&r.tasks_stop) |
diff --git a/embassy-nrf/src/saadc.rs b/embassy-nrf/src/saadc.rs index cf3fb9993..23292924c 100644 --- a/embassy-nrf/src/saadc.rs +++ b/embassy-nrf/src/saadc.rs | |||
| @@ -320,7 +320,9 @@ impl<'d, const N: usize> Saadc<'d, N> { | |||
| 320 | timer.cc(0).write(sample_counter); | 320 | timer.cc(0).write(sample_counter); |
| 321 | timer.cc(0).short_compare_clear(); | 321 | timer.cc(0).short_compare_clear(); |
| 322 | 322 | ||
| 323 | let mut sample_ppi = Ppi::new_one_to_one(ppi_ch2, timer.cc(0).event_compare(), Task::from_reg(&r.tasks_sample)); | 323 | let timer_cc = timer.cc(0); |
| 324 | |||
| 325 | let mut sample_ppi = Ppi::new_one_to_one(ppi_ch2, timer_cc.event_compare(), Task::from_reg(&r.tasks_sample)); | ||
| 324 | 326 | ||
| 325 | timer.start(); | 327 | timer.start(); |
| 326 | 328 | ||
diff --git a/embassy-nrf/src/spim.rs b/embassy-nrf/src/spim.rs index 66bbd1a8f..b7dc332e9 100644 --- a/embassy-nrf/src/spim.rs +++ b/embassy-nrf/src/spim.rs | |||
| @@ -468,25 +468,19 @@ mod eh1 { | |||
| 468 | type Error = Error; | 468 | type Error = Error; |
| 469 | } | 469 | } |
| 470 | 470 | ||
| 471 | impl<'d, T: Instance> embedded_hal_1::spi::SpiBusFlush for Spim<'d, T> { | 471 | impl<'d, T: Instance> embedded_hal_1::spi::SpiBus<u8> for Spim<'d, T> { |
| 472 | fn flush(&mut self) -> Result<(), Self::Error> { | 472 | fn flush(&mut self) -> Result<(), Self::Error> { |
| 473 | Ok(()) | 473 | Ok(()) |
| 474 | } | 474 | } |
| 475 | } | ||
| 476 | 475 | ||
| 477 | impl<'d, T: Instance> embedded_hal_1::spi::SpiBusRead<u8> for Spim<'d, T> { | ||
| 478 | fn read(&mut self, words: &mut [u8]) -> Result<(), Self::Error> { | 476 | fn read(&mut self, words: &mut [u8]) -> Result<(), Self::Error> { |
| 479 | self.blocking_transfer(words, &[]) | 477 | self.blocking_transfer(words, &[]) |
| 480 | } | 478 | } |
| 481 | } | ||
| 482 | 479 | ||
| 483 | impl<'d, T: Instance> embedded_hal_1::spi::SpiBusWrite<u8> for Spim<'d, T> { | ||
| 484 | fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> { | 480 | fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> { |
| 485 | self.blocking_write(words) | 481 | self.blocking_write(words) |
| 486 | } | 482 | } |
| 487 | } | ||
| 488 | 483 | ||
| 489 | impl<'d, T: Instance> embedded_hal_1::spi::SpiBus<u8> for Spim<'d, T> { | ||
| 490 | fn transfer(&mut self, read: &mut [u8], write: &[u8]) -> Result<(), Self::Error> { | 484 | fn transfer(&mut self, read: &mut [u8], write: &[u8]) -> Result<(), Self::Error> { |
| 491 | self.blocking_transfer(read, write) | 485 | self.blocking_transfer(read, write) |
| 492 | } | 486 | } |
| @@ -502,25 +496,19 @@ mod eha { | |||
| 502 | 496 | ||
| 503 | use super::*; | 497 | use super::*; |
| 504 | 498 | ||
| 505 | impl<'d, T: Instance> embedded_hal_async::spi::SpiBusFlush for Spim<'d, T> { | 499 | impl<'d, T: Instance> embedded_hal_async::spi::SpiBus<u8> for Spim<'d, T> { |
| 506 | async fn flush(&mut self) -> Result<(), Error> { | 500 | async fn flush(&mut self) -> Result<(), Error> { |
| 507 | Ok(()) | 501 | Ok(()) |
| 508 | } | 502 | } |
| 509 | } | ||
| 510 | 503 | ||
| 511 | impl<'d, T: Instance> embedded_hal_async::spi::SpiBusRead<u8> for Spim<'d, T> { | ||
| 512 | async fn read(&mut self, words: &mut [u8]) -> Result<(), Error> { | 504 | async fn read(&mut self, words: &mut [u8]) -> Result<(), Error> { |
| 513 | self.read(words).await | 505 | self.read(words).await |
| 514 | } | 506 | } |
| 515 | } | ||
| 516 | 507 | ||
| 517 | impl<'d, T: Instance> embedded_hal_async::spi::SpiBusWrite<u8> for Spim<'d, T> { | ||
| 518 | async fn write(&mut self, data: &[u8]) -> Result<(), Error> { | 508 | async fn write(&mut self, data: &[u8]) -> Result<(), Error> { |
| 519 | self.write(data).await | 509 | self.write(data).await |
| 520 | } | 510 | } |
| 521 | } | ||
| 522 | 511 | ||
| 523 | impl<'d, T: Instance> embedded_hal_async::spi::SpiBus<u8> for Spim<'d, T> { | ||
| 524 | async fn transfer(&mut self, rx: &mut [u8], tx: &[u8]) -> Result<(), Error> { | 512 | async fn transfer(&mut self, rx: &mut [u8], tx: &[u8]) -> Result<(), Error> { |
| 525 | self.transfer(rx, tx).await | 513 | self.transfer(rx, tx).await |
| 526 | } | 514 | } |
diff --git a/embassy-nrf/src/timer.rs b/embassy-nrf/src/timer.rs index dc3757856..04748238d 100644 --- a/embassy-nrf/src/timer.rs +++ b/embassy-nrf/src/timer.rs | |||
| @@ -168,21 +168,21 @@ impl<'d, T: Instance> Timer<'d, T> { | |||
| 168 | /// Returns the START task, for use with PPI. | 168 | /// Returns the START task, for use with PPI. |
| 169 | /// | 169 | /// |
| 170 | /// When triggered, this task starts the timer. | 170 | /// When triggered, this task starts the timer. |
| 171 | pub fn task_start(&self) -> Task { | 171 | pub fn task_start(&self) -> Task<'d> { |
| 172 | Task::from_reg(&T::regs().tasks_start) | 172 | Task::from_reg(&T::regs().tasks_start) |
| 173 | } | 173 | } |
| 174 | 174 | ||
| 175 | /// Returns the STOP task, for use with PPI. | 175 | /// Returns the STOP task, for use with PPI. |
| 176 | /// | 176 | /// |
| 177 | /// When triggered, this task stops the timer. | 177 | /// When triggered, this task stops the timer. |
| 178 | pub fn task_stop(&self) -> Task { | 178 | pub fn task_stop(&self) -> Task<'d> { |
| 179 | Task::from_reg(&T::regs().tasks_stop) | 179 | Task::from_reg(&T::regs().tasks_stop) |
| 180 | } | 180 | } |
| 181 | 181 | ||
| 182 | /// Returns the CLEAR task, for use with PPI. | 182 | /// Returns the CLEAR task, for use with PPI. |
| 183 | /// | 183 | /// |
| 184 | /// When triggered, this task resets the timer's counter to 0. | 184 | /// When triggered, this task resets the timer's counter to 0. |
| 185 | pub fn task_clear(&self) -> Task { | 185 | pub fn task_clear(&self) -> Task<'d> { |
| 186 | Task::from_reg(&T::regs().tasks_clear) | 186 | Task::from_reg(&T::regs().tasks_clear) |
| 187 | } | 187 | } |
| 188 | 188 | ||
| @@ -190,7 +190,7 @@ impl<'d, T: Instance> Timer<'d, T> { | |||
| 190 | /// | 190 | /// |
| 191 | /// When triggered, this task increments the timer's counter by 1. | 191 | /// When triggered, this task increments the timer's counter by 1. |
| 192 | /// Only works in counter mode. | 192 | /// Only works in counter mode. |
| 193 | pub fn task_count(&self) -> Task { | 193 | pub fn task_count(&self) -> Task<'d> { |
| 194 | Task::from_reg(&T::regs().tasks_count) | 194 | Task::from_reg(&T::regs().tasks_count) |
| 195 | } | 195 | } |
| 196 | 196 | ||
| @@ -258,14 +258,14 @@ impl<'d, T: Instance> Cc<'d, T> { | |||
| 258 | /// Returns this CC register's CAPTURE task, for use with PPI. | 258 | /// Returns this CC register's CAPTURE task, for use with PPI. |
| 259 | /// | 259 | /// |
| 260 | /// When triggered, this task will capture the current value of the timer's counter in this register. | 260 | /// When triggered, this task will capture the current value of the timer's counter in this register. |
| 261 | pub fn task_capture(&self) -> Task { | 261 | pub fn task_capture(&self) -> Task<'d> { |
| 262 | Task::from_reg(&T::regs().tasks_capture) | 262 | Task::from_reg(&T::regs().tasks_capture) |
| 263 | } | 263 | } |
| 264 | 264 | ||
| 265 | /// Returns this CC register's COMPARE event, for use with PPI. | 265 | /// Returns this CC register's COMPARE event, for use with PPI. |
| 266 | /// | 266 | /// |
| 267 | /// This event will fire when the timer's counter reaches the value in this CC register. | 267 | /// This event will fire when the timer's counter reaches the value in this CC register. |
| 268 | pub fn event_compare(&self) -> Event { | 268 | pub fn event_compare(&self) -> Event<'d> { |
| 269 | Event::from_reg(&T::regs().events_compare[self.n]) | 269 | Event::from_reg(&T::regs().events_compare[self.n]) |
| 270 | } | 270 | } |
| 271 | 271 | ||
diff --git a/embassy-rp/Cargo.toml b/embassy-rp/Cargo.toml index 66823771a..8f3ed885d 100644 --- a/embassy-rp/Cargo.toml +++ b/embassy-rp/Cargo.toml | |||
| @@ -56,7 +56,7 @@ unstable-traits = ["embedded-hal-1", "embedded-hal-nb"] | |||
| 56 | 56 | ||
| 57 | [dependencies] | 57 | [dependencies] |
| 58 | embassy-sync = { version = "0.2.0", path = "../embassy-sync" } | 58 | embassy-sync = { version = "0.2.0", path = "../embassy-sync" } |
| 59 | embassy-time = { version = "0.1.0", path = "../embassy-time", features = [ "tick-hz-1_000_000" ] } | 59 | embassy-time = { version = "0.1.2", path = "../embassy-time", features = [ "tick-hz-1_000_000" ] } |
| 60 | embassy-futures = { version = "0.1.0", path = "../embassy-futures" } | 60 | embassy-futures = { version = "0.1.0", path = "../embassy-futures" } |
| 61 | embassy-hal-common = {version = "0.1.0", path = "../embassy-hal-common", features = ["cortex-m", "prio-bits-2"] } | 61 | embassy-hal-common = {version = "0.1.0", path = "../embassy-hal-common", features = ["cortex-m", "prio-bits-2"] } |
| 62 | embassy-embedded-hal = {version = "0.1.0", path = "../embassy-embedded-hal" } | 62 | embassy-embedded-hal = {version = "0.1.0", path = "../embassy-embedded-hal" } |
| @@ -79,9 +79,9 @@ fixed = "1.23.1" | |||
| 79 | rp-pac = { version = "6" } | 79 | rp-pac = { version = "6" } |
| 80 | 80 | ||
| 81 | embedded-hal-02 = { package = "embedded-hal", version = "0.2.6", features = ["unproven"] } | 81 | embedded-hal-02 = { package = "embedded-hal", version = "0.2.6", features = ["unproven"] } |
| 82 | embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-alpha.10", optional = true} | 82 | embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-alpha.11", optional = true} |
| 83 | embedded-hal-async = { version = "=0.2.0-alpha.1", optional = true} | 83 | embedded-hal-async = { version = "=0.2.0-alpha.2", optional = true} |
| 84 | embedded-hal-nb = { version = "=1.0.0-alpha.2", optional = true} | 84 | embedded-hal-nb = { version = "=1.0.0-alpha.3", optional = true} |
| 85 | 85 | ||
| 86 | paste = "1.0" | 86 | paste = "1.0" |
| 87 | pio-proc = {version= "0.2" } | 87 | pio-proc = {version= "0.2" } |
diff --git a/embassy-rp/src/adc.rs b/embassy-rp/src/adc.rs index 699a0d61d..dfa1b877a 100644 --- a/embassy-rp/src/adc.rs +++ b/embassy-rp/src/adc.rs | |||
| @@ -3,22 +3,17 @@ use core::marker::PhantomData; | |||
| 3 | use core::sync::atomic::{compiler_fence, Ordering}; | 3 | use core::sync::atomic::{compiler_fence, Ordering}; |
| 4 | use core::task::Poll; | 4 | use core::task::Poll; |
| 5 | 5 | ||
| 6 | use embassy_hal_common::{into_ref, PeripheralRef}; | ||
| 6 | use embassy_sync::waitqueue::AtomicWaker; | 7 | use embassy_sync::waitqueue::AtomicWaker; |
| 7 | use embedded_hal_02::adc::{Channel, OneShot}; | ||
| 8 | 8 | ||
| 9 | use crate::gpio::Pin; | 9 | use crate::gpio::sealed::Pin as GpioPin; |
| 10 | use crate::gpio::{self, AnyPin, Pull}; | ||
| 10 | use crate::interrupt::typelevel::Binding; | 11 | use crate::interrupt::typelevel::Binding; |
| 11 | use crate::interrupt::InterruptExt; | 12 | use crate::interrupt::InterruptExt; |
| 12 | use crate::peripherals::ADC; | 13 | use crate::peripherals::ADC; |
| 13 | use crate::{interrupt, pac, peripherals, Peripheral}; | 14 | use crate::{interrupt, pac, peripherals, Peripheral}; |
| 14 | static WAKER: AtomicWaker = AtomicWaker::new(); | ||
| 15 | 15 | ||
| 16 | #[derive(Debug, Clone, Copy, PartialEq, Eq)] | 16 | static WAKER: AtomicWaker = AtomicWaker::new(); |
| 17 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 18 | #[non_exhaustive] | ||
| 19 | pub enum Error { | ||
| 20 | // No errors for now | ||
| 21 | } | ||
| 22 | 17 | ||
| 23 | #[non_exhaustive] | 18 | #[non_exhaustive] |
| 24 | pub struct Config {} | 19 | pub struct Config {} |
| @@ -28,11 +23,65 @@ impl Default for Config { | |||
| 28 | Self {} | 23 | Self {} |
| 29 | } | 24 | } |
| 30 | } | 25 | } |
| 31 | pub struct Adc<'d> { | 26 | |
| 32 | phantom: PhantomData<&'d ADC>, | 27 | pub struct Pin<'p> { |
| 28 | pin: PeripheralRef<'p, AnyPin>, | ||
| 29 | } | ||
| 30 | |||
| 31 | impl<'p> Pin<'p> { | ||
| 32 | pub fn new(pin: impl Peripheral<P = impl AdcPin + 'p> + 'p, pull: Pull) -> Self { | ||
| 33 | into_ref!(pin); | ||
| 34 | pin.pad_ctrl().modify(|w| { | ||
| 35 | // manual says: | ||
| 36 | // | ||
| 37 | // > When using an ADC input shared with a GPIO pin, the pin’s | ||
| 38 | // > digital functions must be disabled by setting IE low and OD | ||
| 39 | // > high in the pin’s pad control register | ||
| 40 | w.set_ie(false); | ||
| 41 | w.set_od(true); | ||
| 42 | w.set_pue(pull == Pull::Up); | ||
| 43 | w.set_pde(pull == Pull::Down); | ||
| 44 | }); | ||
| 45 | Self { pin: pin.map_into() } | ||
| 46 | } | ||
| 47 | |||
| 48 | fn channel(&self) -> u8 { | ||
| 49 | // this requires adc pins to be sequential and matching the adc channels, | ||
| 50 | // which is the case for rp2040 | ||
| 51 | self.pin._pin() - 26 | ||
| 52 | } | ||
| 53 | } | ||
| 54 | |||
| 55 | impl<'d> Drop for Pin<'d> { | ||
| 56 | fn drop(&mut self) { | ||
| 57 | self.pin.pad_ctrl().modify(|w| { | ||
| 58 | w.set_ie(true); | ||
| 59 | w.set_od(false); | ||
| 60 | w.set_pue(false); | ||
| 61 | w.set_pde(true); | ||
| 62 | }); | ||
| 63 | } | ||
| 64 | } | ||
| 65 | |||
| 66 | #[derive(Debug, Eq, PartialEq, Copy, Clone)] | ||
| 67 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 68 | pub enum Error { | ||
| 69 | ConversionFailed, | ||
| 70 | } | ||
| 71 | |||
| 72 | pub trait Mode {} | ||
| 73 | |||
| 74 | pub struct Async; | ||
| 75 | impl Mode for Async {} | ||
| 76 | |||
| 77 | pub struct Blocking; | ||
| 78 | impl Mode for Blocking {} | ||
| 79 | |||
| 80 | pub struct Adc<'d, M: Mode> { | ||
| 81 | phantom: PhantomData<(&'d ADC, M)>, | ||
| 33 | } | 82 | } |
| 34 | 83 | ||
| 35 | impl<'d> Adc<'d> { | 84 | impl<'d, M: Mode> Adc<'d, M> { |
| 36 | #[inline] | 85 | #[inline] |
| 37 | fn regs() -> pac::adc::Adc { | 86 | fn regs() -> pac::adc::Adc { |
| 38 | pac::ADC | 87 | pac::ADC |
| @@ -45,11 +94,7 @@ impl<'d> Adc<'d> { | |||
| 45 | ret | 94 | ret |
| 46 | } | 95 | } |
| 47 | 96 | ||
| 48 | pub fn new( | 97 | fn setup() { |
| 49 | _inner: impl Peripheral<P = ADC> + 'd, | ||
| 50 | _irq: impl Binding<interrupt::typelevel::ADC_IRQ_FIFO, InterruptHandler>, | ||
| 51 | _config: Config, | ||
| 52 | ) -> Self { | ||
| 53 | let reset = Self::reset(); | 98 | let reset = Self::reset(); |
| 54 | crate::reset::reset(reset); | 99 | crate::reset::reset(reset); |
| 55 | crate::reset::unreset_wait(reset); | 100 | crate::reset::unreset_wait(reset); |
| @@ -58,6 +103,43 @@ impl<'d> Adc<'d> { | |||
| 58 | r.cs().write(|w| w.set_en(true)); | 103 | r.cs().write(|w| w.set_en(true)); |
| 59 | // Wait for ADC ready | 104 | // Wait for ADC ready |
| 60 | while !r.cs().read().ready() {} | 105 | while !r.cs().read().ready() {} |
| 106 | } | ||
| 107 | |||
| 108 | fn sample_blocking(channel: u8) -> Result<u16, Error> { | ||
| 109 | let r = Self::regs(); | ||
| 110 | r.cs().modify(|w| { | ||
| 111 | w.set_ainsel(channel); | ||
| 112 | w.set_start_once(true); | ||
| 113 | w.set_err(true); | ||
| 114 | }); | ||
| 115 | while !r.cs().read().ready() {} | ||
| 116 | match r.cs().read().err() { | ||
| 117 | true => Err(Error::ConversionFailed), | ||
| 118 | false => Ok(r.result().read().result().into()), | ||
| 119 | } | ||
| 120 | } | ||
| 121 | |||
| 122 | pub fn blocking_read(&mut self, pin: &mut Pin) -> Result<u16, Error> { | ||
| 123 | Self::sample_blocking(pin.channel()) | ||
| 124 | } | ||
| 125 | |||
| 126 | pub fn blocking_read_temperature(&mut self) -> Result<u16, Error> { | ||
| 127 | let r = Self::regs(); | ||
| 128 | r.cs().modify(|w| w.set_ts_en(true)); | ||
| 129 | while !r.cs().read().ready() {} | ||
| 130 | let result = Self::sample_blocking(4); | ||
| 131 | r.cs().modify(|w| w.set_ts_en(false)); | ||
| 132 | result | ||
| 133 | } | ||
| 134 | } | ||
| 135 | |||
| 136 | impl<'d> Adc<'d, Async> { | ||
| 137 | pub fn new( | ||
| 138 | _inner: impl Peripheral<P = ADC> + 'd, | ||
| 139 | _irq: impl Binding<interrupt::typelevel::ADC_IRQ_FIFO, InterruptHandler>, | ||
| 140 | _config: Config, | ||
| 141 | ) -> Self { | ||
| 142 | Self::setup(); | ||
| 61 | 143 | ||
| 62 | // Setup IRQ | 144 | // Setup IRQ |
| 63 | interrupt::ADC_IRQ_FIFO.unpend(); | 145 | interrupt::ADC_IRQ_FIFO.unpend(); |
| @@ -80,102 +162,77 @@ impl<'d> Adc<'d> { | |||
| 80 | .await; | 162 | .await; |
| 81 | } | 163 | } |
| 82 | 164 | ||
| 83 | pub async fn read<PIN: Channel<Adc<'d>, ID = u8> + Pin>(&mut self, pin: &mut PIN) -> u16 { | 165 | async fn sample_async(channel: u8) -> Result<u16, Error> { |
| 84 | let r = Self::regs(); | 166 | let r = Self::regs(); |
| 85 | // disable pull-down and pull-up resistors | ||
| 86 | // pull-down resistors are enabled by default | ||
| 87 | pin.pad_ctrl().modify(|w| { | ||
| 88 | w.set_ie(true); | ||
| 89 | let (pu, pd) = (false, false); | ||
| 90 | w.set_pue(pu); | ||
| 91 | w.set_pde(pd); | ||
| 92 | }); | ||
| 93 | r.cs().modify(|w| { | 167 | r.cs().modify(|w| { |
| 94 | w.set_ainsel(PIN::channel()); | 168 | w.set_ainsel(channel); |
| 95 | w.set_start_once(true) | 169 | w.set_start_once(true); |
| 170 | w.set_err(true); | ||
| 96 | }); | 171 | }); |
| 97 | Self::wait_for_ready().await; | 172 | Self::wait_for_ready().await; |
| 98 | r.result().read().result().into() | 173 | match r.cs().read().err() { |
| 174 | true => Err(Error::ConversionFailed), | ||
| 175 | false => Ok(r.result().read().result().into()), | ||
| 176 | } | ||
| 99 | } | 177 | } |
| 100 | 178 | ||
| 101 | pub async fn read_temperature(&mut self) -> u16 { | 179 | pub async fn read(&mut self, pin: &mut Pin<'_>) -> Result<u16, Error> { |
| 180 | Self::sample_async(pin.channel()).await | ||
| 181 | } | ||
| 182 | |||
| 183 | pub async fn read_temperature(&mut self) -> Result<u16, Error> { | ||
| 102 | let r = Self::regs(); | 184 | let r = Self::regs(); |
| 103 | r.cs().modify(|w| w.set_ts_en(true)); | 185 | r.cs().modify(|w| w.set_ts_en(true)); |
| 104 | if !r.cs().read().ready() { | 186 | if !r.cs().read().ready() { |
| 105 | Self::wait_for_ready().await; | 187 | Self::wait_for_ready().await; |
| 106 | } | 188 | } |
| 107 | r.cs().modify(|w| { | 189 | let result = Self::sample_async(4).await; |
| 108 | w.set_ainsel(4); | 190 | r.cs().modify(|w| w.set_ts_en(false)); |
| 109 | w.set_start_once(true) | 191 | result |
| 110 | }); | ||
| 111 | Self::wait_for_ready().await; | ||
| 112 | r.result().read().result().into() | ||
| 113 | } | 192 | } |
| 193 | } | ||
| 114 | 194 | ||
| 115 | pub fn blocking_read<PIN: Channel<Adc<'d>, ID = u8> + Pin>(&mut self, pin: &mut PIN) -> u16 { | 195 | impl<'d> Adc<'d, Blocking> { |
| 116 | let r = Self::regs(); | 196 | pub fn new_blocking(_inner: impl Peripheral<P = ADC> + 'd, _config: Config) -> Self { |
| 117 | pin.pad_ctrl().modify(|w| { | 197 | Self::setup(); |
| 118 | w.set_ie(true); | ||
| 119 | let (pu, pd) = (false, false); | ||
| 120 | w.set_pue(pu); | ||
| 121 | w.set_pde(pd); | ||
| 122 | }); | ||
| 123 | r.cs().modify(|w| { | ||
| 124 | w.set_ainsel(PIN::channel()); | ||
| 125 | w.set_start_once(true) | ||
| 126 | }); | ||
| 127 | while !r.cs().read().ready() {} | ||
| 128 | r.result().read().result().into() | ||
| 129 | } | ||
| 130 | 198 | ||
| 131 | pub fn blocking_read_temperature(&mut self) -> u16 { | 199 | Self { phantom: PhantomData } |
| 132 | let r = Self::regs(); | ||
| 133 | r.cs().modify(|w| w.set_ts_en(true)); | ||
| 134 | while !r.cs().read().ready() {} | ||
| 135 | r.cs().modify(|w| { | ||
| 136 | w.set_ainsel(4); | ||
| 137 | w.set_start_once(true) | ||
| 138 | }); | ||
| 139 | while !r.cs().read().ready() {} | ||
| 140 | r.result().read().result().into() | ||
| 141 | } | 200 | } |
| 142 | } | 201 | } |
| 143 | 202 | ||
| 144 | macro_rules! impl_pin { | ||
| 145 | ($pin:ident, $channel:expr) => { | ||
| 146 | impl Channel<Adc<'static>> for peripherals::$pin { | ||
| 147 | type ID = u8; | ||
| 148 | fn channel() -> u8 { | ||
| 149 | $channel | ||
| 150 | } | ||
| 151 | } | ||
| 152 | }; | ||
| 153 | } | ||
| 154 | |||
| 155 | pub struct InterruptHandler { | 203 | pub struct InterruptHandler { |
| 156 | _empty: (), | 204 | _empty: (), |
| 157 | } | 205 | } |
| 158 | 206 | ||
| 159 | impl interrupt::typelevel::Handler<interrupt::typelevel::ADC_IRQ_FIFO> for InterruptHandler { | 207 | impl interrupt::typelevel::Handler<interrupt::typelevel::ADC_IRQ_FIFO> for InterruptHandler { |
| 160 | unsafe fn on_interrupt() { | 208 | unsafe fn on_interrupt() { |
| 161 | let r = Adc::regs(); | 209 | let r = Adc::<Async>::regs(); |
| 162 | r.inte().write(|w| w.set_fifo(false)); | 210 | r.inte().write(|w| w.set_fifo(false)); |
| 163 | WAKER.wake(); | 211 | WAKER.wake(); |
| 164 | } | 212 | } |
| 165 | } | 213 | } |
| 166 | 214 | ||
| 215 | mod sealed { | ||
| 216 | pub trait AdcPin: crate::gpio::sealed::Pin { | ||
| 217 | fn channel(&mut self) -> u8; | ||
| 218 | } | ||
| 219 | } | ||
| 220 | |||
| 221 | pub trait AdcPin: sealed::AdcPin + gpio::Pin {} | ||
| 222 | |||
| 223 | macro_rules! impl_pin { | ||
| 224 | ($pin:ident, $channel:expr) => { | ||
| 225 | impl sealed::AdcPin for peripherals::$pin { | ||
| 226 | fn channel(&mut self) -> u8 { | ||
| 227 | $channel | ||
| 228 | } | ||
| 229 | } | ||
| 230 | |||
| 231 | impl AdcPin for peripherals::$pin {} | ||
| 232 | }; | ||
| 233 | } | ||
| 234 | |||
| 167 | impl_pin!(PIN_26, 0); | 235 | impl_pin!(PIN_26, 0); |
| 168 | impl_pin!(PIN_27, 1); | 236 | impl_pin!(PIN_27, 1); |
| 169 | impl_pin!(PIN_28, 2); | 237 | impl_pin!(PIN_28, 2); |
| 170 | impl_pin!(PIN_29, 3); | 238 | impl_pin!(PIN_29, 3); |
| 171 | |||
| 172 | impl<WORD, PIN> OneShot<Adc<'static>, WORD, PIN> for Adc<'static> | ||
| 173 | where | ||
| 174 | WORD: From<u16>, | ||
| 175 | PIN: Channel<Adc<'static>, ID = u8> + Pin, | ||
| 176 | { | ||
| 177 | type Error = (); | ||
| 178 | fn read(&mut self, pin: &mut PIN) -> nb::Result<WORD, Self::Error> { | ||
| 179 | Ok(self.blocking_read(pin).into()) | ||
| 180 | } | ||
| 181 | } | ||
diff --git a/embassy-rp/src/clocks.rs b/embassy-rp/src/clocks.rs index ddd61d224..acb21dce5 100644 --- a/embassy-rp/src/clocks.rs +++ b/embassy-rp/src/clocks.rs | |||
| @@ -308,6 +308,7 @@ pub(crate) unsafe fn init(config: ClockConfig) { | |||
| 308 | // - QSPI (we're using it to run this code!) | 308 | // - QSPI (we're using it to run this code!) |
| 309 | // - PLLs (it may be suicide if that's what's clocking us) | 309 | // - PLLs (it may be suicide if that's what's clocking us) |
| 310 | // - USB, SYSCFG (breaks usb-to-swd on core1) | 310 | // - USB, SYSCFG (breaks usb-to-swd on core1) |
| 311 | // - RTC (else there would be no more time...) | ||
| 311 | let mut peris = reset::ALL_PERIPHERALS; | 312 | let mut peris = reset::ALL_PERIPHERALS; |
| 312 | peris.set_io_qspi(false); | 313 | peris.set_io_qspi(false); |
| 313 | // peris.set_io_bank0(false); // might be suicide if we're clocked from gpin | 314 | // peris.set_io_bank0(false); // might be suicide if we're clocked from gpin |
| @@ -317,6 +318,7 @@ pub(crate) unsafe fn init(config: ClockConfig) { | |||
| 317 | // TODO investigate if usb should be unreset here | 318 | // TODO investigate if usb should be unreset here |
| 318 | peris.set_usbctrl(false); | 319 | peris.set_usbctrl(false); |
| 319 | peris.set_syscfg(false); | 320 | peris.set_syscfg(false); |
| 321 | peris.set_rtc(false); | ||
| 320 | reset::reset(peris); | 322 | reset::reset(peris); |
| 321 | 323 | ||
| 322 | // Disable resus that may be enabled from previous software | 324 | // Disable resus that may be enabled from previous software |
diff --git a/embassy-rp/src/gpio.rs b/embassy-rp/src/gpio.rs index f8048a4dd..a3d330cdc 100644 --- a/embassy-rp/src/gpio.rs +++ b/embassy-rp/src/gpio.rs | |||
| @@ -41,7 +41,7 @@ impl From<Level> for bool { | |||
| 41 | } | 41 | } |
| 42 | 42 | ||
| 43 | /// Represents a pull setting for an input. | 43 | /// Represents a pull setting for an input. |
| 44 | #[derive(Debug, Eq, PartialEq)] | 44 | #[derive(Debug, Clone, Copy, Eq, PartialEq)] |
| 45 | pub enum Pull { | 45 | pub enum Pull { |
| 46 | None, | 46 | None, |
| 47 | Up, | 47 | Up, |
| @@ -566,13 +566,13 @@ impl<'d, T: Pin> Flex<'d, T> { | |||
| 566 | /// Is the output level high? | 566 | /// Is the output level high? |
| 567 | #[inline] | 567 | #[inline] |
| 568 | pub fn is_set_high(&self) -> bool { | 568 | pub fn is_set_high(&self) -> bool { |
| 569 | (self.pin.sio_out().value().read() & self.bit()) == 0 | 569 | !self.is_set_low() |
| 570 | } | 570 | } |
| 571 | 571 | ||
| 572 | /// Is the output level low? | 572 | /// Is the output level low? |
| 573 | #[inline] | 573 | #[inline] |
| 574 | pub fn is_set_low(&self) -> bool { | 574 | pub fn is_set_low(&self) -> bool { |
| 575 | !self.is_set_high() | 575 | (self.pin.sio_out().value().read() & self.bit()) == 0 |
| 576 | } | 576 | } |
| 577 | 577 | ||
| 578 | /// What level output is set to | 578 | /// What level output is set to |
diff --git a/embassy-rp/src/lib.rs b/embassy-rp/src/lib.rs index 4fd3cb46a..4f205a16e 100644 --- a/embassy-rp/src/lib.rs +++ b/embassy-rp/src/lib.rs | |||
| @@ -252,7 +252,6 @@ pub fn init(config: config::Config) -> Peripherals { | |||
| 252 | #[cfg(feature = "time-driver")] | 252 | #[cfg(feature = "time-driver")] |
| 253 | timer::init(); | 253 | timer::init(); |
| 254 | dma::init(); | 254 | dma::init(); |
| 255 | pio::init(); | ||
| 256 | gpio::init(); | 255 | gpio::init(); |
| 257 | } | 256 | } |
| 258 | 257 | ||
diff --git a/embassy-rp/src/pio.rs b/embassy-rp/src/pio.rs index 30648e8ea..72a2f44ed 100644 --- a/embassy-rp/src/pio.rs +++ b/embassy-rp/src/pio.rs | |||
| @@ -16,12 +16,12 @@ use pio::{SideSet, Wrap}; | |||
| 16 | use crate::dma::{Channel, Transfer, Word}; | 16 | use crate::dma::{Channel, Transfer, Word}; |
| 17 | use crate::gpio::sealed::Pin as SealedPin; | 17 | use crate::gpio::sealed::Pin as SealedPin; |
| 18 | use crate::gpio::{self, AnyPin, Drive, Level, Pull, SlewRate}; | 18 | use crate::gpio::{self, AnyPin, Drive, Level, Pull, SlewRate}; |
| 19 | use crate::interrupt::InterruptExt; | 19 | use crate::interrupt::typelevel::{Binding, Handler, Interrupt}; |
| 20 | use crate::pac::dma::vals::TreqSel; | 20 | use crate::pac::dma::vals::TreqSel; |
| 21 | use crate::relocate::RelocatedProgram; | 21 | use crate::relocate::RelocatedProgram; |
| 22 | use crate::{interrupt, pac, peripherals, pio_instr_util, RegExt}; | 22 | use crate::{pac, peripherals, pio_instr_util, RegExt}; |
| 23 | 23 | ||
| 24 | struct Wakers([AtomicWaker; 12]); | 24 | pub struct Wakers([AtomicWaker; 12]); |
| 25 | 25 | ||
| 26 | impl Wakers { | 26 | impl Wakers { |
| 27 | #[inline(always)] | 27 | #[inline(always)] |
| @@ -38,10 +38,6 @@ impl Wakers { | |||
| 38 | } | 38 | } |
| 39 | } | 39 | } |
| 40 | 40 | ||
| 41 | const NEW_AW: AtomicWaker = AtomicWaker::new(); | ||
| 42 | const PIO_WAKERS_INIT: Wakers = Wakers([NEW_AW; 12]); | ||
| 43 | static WAKERS: [Wakers; 2] = [PIO_WAKERS_INIT; 2]; | ||
| 44 | |||
| 45 | #[derive(Clone, Copy, PartialEq, Eq, Default, Debug)] | 41 | #[derive(Clone, Copy, PartialEq, Eq, Default, Debug)] |
| 46 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | 42 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] |
| 47 | #[repr(u8)] | 43 | #[repr(u8)] |
| @@ -85,42 +81,20 @@ const RXNEMPTY_MASK: u32 = 1 << 0; | |||
| 85 | const TXNFULL_MASK: u32 = 1 << 4; | 81 | const TXNFULL_MASK: u32 = 1 << 4; |
| 86 | const SMIRQ_MASK: u32 = 1 << 8; | 82 | const SMIRQ_MASK: u32 = 1 << 8; |
| 87 | 83 | ||
| 88 | #[cfg(feature = "rt")] | 84 | pub struct InterruptHandler<PIO: Instance> { |
| 89 | #[interrupt] | 85 | _pio: PhantomData<PIO>, |
| 90 | fn PIO0_IRQ_0() { | ||
| 91 | use crate::pac; | ||
| 92 | let ints = pac::PIO0.irqs(0).ints().read().0; | ||
| 93 | for bit in 0..12 { | ||
| 94 | if ints & (1 << bit) != 0 { | ||
| 95 | WAKERS[0].0[bit].wake(); | ||
| 96 | } | ||
| 97 | } | ||
| 98 | pac::PIO0.irqs(0).inte().write_clear(|m| m.0 = ints); | ||
| 99 | } | 86 | } |
| 100 | 87 | ||
| 101 | #[cfg(feature = "rt")] | 88 | impl<PIO: Instance> Handler<PIO::Interrupt> for InterruptHandler<PIO> { |
| 102 | #[interrupt] | 89 | unsafe fn on_interrupt() { |
| 103 | fn PIO1_IRQ_0() { | 90 | let ints = PIO::PIO.irqs(0).ints().read().0; |
| 104 | use crate::pac; | 91 | for bit in 0..12 { |
| 105 | let ints = pac::PIO1.irqs(0).ints().read().0; | 92 | if ints & (1 << bit) != 0 { |
| 106 | for bit in 0..12 { | 93 | PIO::wakers().0[bit].wake(); |
| 107 | if ints & (1 << bit) != 0 { | 94 | } |
| 108 | WAKERS[1].0[bit].wake(); | ||
| 109 | } | 95 | } |
| 96 | PIO::PIO.irqs(0).inte().write_clear(|m| m.0 = ints); | ||
| 110 | } | 97 | } |
| 111 | pac::PIO1.irqs(0).inte().write_clear(|m| m.0 = ints); | ||
| 112 | } | ||
| 113 | |||
| 114 | pub(crate) unsafe fn init() { | ||
| 115 | interrupt::PIO0_IRQ_0.disable(); | ||
| 116 | interrupt::PIO0_IRQ_0.set_priority(interrupt::Priority::P3); | ||
| 117 | pac::PIO0.irqs(0).inte().write(|m| m.0 = 0); | ||
| 118 | interrupt::PIO0_IRQ_0.enable(); | ||
| 119 | |||
| 120 | interrupt::PIO1_IRQ_0.disable(); | ||
| 121 | interrupt::PIO1_IRQ_0.set_priority(interrupt::Priority::P3); | ||
| 122 | pac::PIO1.irqs(0).inte().write(|m| m.0 = 0); | ||
| 123 | interrupt::PIO1_IRQ_0.enable(); | ||
| 124 | } | 98 | } |
| 125 | 99 | ||
| 126 | /// Future that waits for TX-FIFO to become writable | 100 | /// Future that waits for TX-FIFO to become writable |
| @@ -144,7 +118,7 @@ impl<'a, 'd, PIO: Instance, const SM: usize> Future for FifoOutFuture<'a, 'd, PI | |||
| 144 | if self.get_mut().sm_tx.try_push(value) { | 118 | if self.get_mut().sm_tx.try_push(value) { |
| 145 | Poll::Ready(()) | 119 | Poll::Ready(()) |
| 146 | } else { | 120 | } else { |
| 147 | WAKERS[PIO::PIO_NO as usize].fifo_out()[SM].register(cx.waker()); | 121 | PIO::wakers().fifo_out()[SM].register(cx.waker()); |
| 148 | PIO::PIO.irqs(0).inte().write_set(|m| { | 122 | PIO::PIO.irqs(0).inte().write_set(|m| { |
| 149 | m.0 = TXNFULL_MASK << SM; | 123 | m.0 = TXNFULL_MASK << SM; |
| 150 | }); | 124 | }); |
| @@ -181,7 +155,7 @@ impl<'a, 'd, PIO: Instance, const SM: usize> Future for FifoInFuture<'a, 'd, PIO | |||
| 181 | if let Some(v) = self.sm_rx.try_pull() { | 155 | if let Some(v) = self.sm_rx.try_pull() { |
| 182 | Poll::Ready(v) | 156 | Poll::Ready(v) |
| 183 | } else { | 157 | } else { |
| 184 | WAKERS[PIO::PIO_NO as usize].fifo_in()[SM].register(cx.waker()); | 158 | PIO::wakers().fifo_in()[SM].register(cx.waker()); |
| 185 | PIO::PIO.irqs(0).inte().write_set(|m| { | 159 | PIO::PIO.irqs(0).inte().write_set(|m| { |
| 186 | m.0 = RXNEMPTY_MASK << SM; | 160 | m.0 = RXNEMPTY_MASK << SM; |
| 187 | }); | 161 | }); |
| @@ -217,7 +191,7 @@ impl<'a, 'd, PIO: Instance> Future for IrqFuture<'a, 'd, PIO> { | |||
| 217 | return Poll::Ready(()); | 191 | return Poll::Ready(()); |
| 218 | } | 192 | } |
| 219 | 193 | ||
| 220 | WAKERS[PIO::PIO_NO as usize].irq()[self.irq_no as usize].register(cx.waker()); | 194 | PIO::wakers().irq()[self.irq_no as usize].register(cx.waker()); |
| 221 | PIO::PIO.irqs(0).inte().write_set(|m| { | 195 | PIO::PIO.irqs(0).inte().write_set(|m| { |
| 222 | m.0 = SMIRQ_MASK << self.irq_no; | 196 | m.0 = SMIRQ_MASK << self.irq_no; |
| 223 | }); | 197 | }); |
| @@ -949,9 +923,11 @@ pub struct Pio<'d, PIO: Instance> { | |||
| 949 | } | 923 | } |
| 950 | 924 | ||
| 951 | impl<'d, PIO: Instance> Pio<'d, PIO> { | 925 | impl<'d, PIO: Instance> Pio<'d, PIO> { |
| 952 | pub fn new(_pio: impl Peripheral<P = PIO> + 'd) -> Self { | 926 | pub fn new(_pio: impl Peripheral<P = PIO> + 'd, _irq: impl Binding<PIO::Interrupt, InterruptHandler<PIO>>) -> Self { |
| 953 | PIO::state().users.store(5, Ordering::Release); | 927 | PIO::state().users.store(5, Ordering::Release); |
| 954 | PIO::state().used_pins.store(0, Ordering::Release); | 928 | PIO::state().used_pins.store(0, Ordering::Release); |
| 929 | PIO::Interrupt::unpend(); | ||
| 930 | unsafe { PIO::Interrupt::enable() }; | ||
| 955 | Self { | 931 | Self { |
| 956 | common: Common { | 932 | common: Common { |
| 957 | instructions_used: 0, | 933 | instructions_used: 0, |
| @@ -1017,6 +993,15 @@ mod sealed { | |||
| 1017 | const PIO_NO: u8; | 993 | const PIO_NO: u8; |
| 1018 | const PIO: &'static crate::pac::pio::Pio; | 994 | const PIO: &'static crate::pac::pio::Pio; |
| 1019 | const FUNCSEL: crate::pac::io::vals::Gpio0ctrlFuncsel; | 995 | const FUNCSEL: crate::pac::io::vals::Gpio0ctrlFuncsel; |
| 996 | type Interrupt: crate::interrupt::typelevel::Interrupt; | ||
| 997 | |||
| 998 | #[inline] | ||
| 999 | fn wakers() -> &'static Wakers { | ||
| 1000 | const NEW_AW: AtomicWaker = AtomicWaker::new(); | ||
| 1001 | static WAKERS: Wakers = Wakers([NEW_AW; 12]); | ||
| 1002 | |||
| 1003 | &WAKERS | ||
| 1004 | } | ||
| 1020 | 1005 | ||
| 1021 | #[inline] | 1006 | #[inline] |
| 1022 | fn state() -> &'static State { | 1007 | fn state() -> &'static State { |
| @@ -1033,18 +1018,19 @@ mod sealed { | |||
| 1033 | pub trait Instance: sealed::Instance + Sized + Unpin {} | 1018 | pub trait Instance: sealed::Instance + Sized + Unpin {} |
| 1034 | 1019 | ||
| 1035 | macro_rules! impl_pio { | 1020 | macro_rules! impl_pio { |
| 1036 | ($name:ident, $pio:expr, $pac:ident, $funcsel:ident) => { | 1021 | ($name:ident, $pio:expr, $pac:ident, $funcsel:ident, $irq:ident) => { |
| 1037 | impl sealed::Instance for peripherals::$name { | 1022 | impl sealed::Instance for peripherals::$name { |
| 1038 | const PIO_NO: u8 = $pio; | 1023 | const PIO_NO: u8 = $pio; |
| 1039 | const PIO: &'static pac::pio::Pio = &pac::$pac; | 1024 | const PIO: &'static pac::pio::Pio = &pac::$pac; |
| 1040 | const FUNCSEL: pac::io::vals::Gpio0ctrlFuncsel = pac::io::vals::Gpio0ctrlFuncsel::$funcsel; | 1025 | const FUNCSEL: pac::io::vals::Gpio0ctrlFuncsel = pac::io::vals::Gpio0ctrlFuncsel::$funcsel; |
| 1026 | type Interrupt = crate::interrupt::typelevel::$irq; | ||
| 1041 | } | 1027 | } |
| 1042 | impl Instance for peripherals::$name {} | 1028 | impl Instance for peripherals::$name {} |
| 1043 | }; | 1029 | }; |
| 1044 | } | 1030 | } |
| 1045 | 1031 | ||
| 1046 | impl_pio!(PIO0, 0, PIO0, PIO0_0); | 1032 | impl_pio!(PIO0, 0, PIO0, PIO0_0, PIO0_IRQ_0); |
| 1047 | impl_pio!(PIO1, 1, PIO1, PIO1_0); | 1033 | impl_pio!(PIO1, 1, PIO1, PIO1_0, PIO1_IRQ_0); |
| 1048 | 1034 | ||
| 1049 | pub trait PioPin: sealed::PioPin + gpio::Pin {} | 1035 | pub trait PioPin: sealed::PioPin + gpio::Pin {} |
| 1050 | 1036 | ||
diff --git a/embassy-rp/src/rtc/datetime_no_deps.rs b/embassy-rp/src/rtc/datetime_no_deps.rs index 92770e984..ea899c339 100644 --- a/embassy-rp/src/rtc/datetime_no_deps.rs +++ b/embassy-rp/src/rtc/datetime_no_deps.rs | |||
| @@ -25,6 +25,7 @@ pub enum Error { | |||
| 25 | } | 25 | } |
| 26 | 26 | ||
| 27 | /// Structure containing date and time information | 27 | /// Structure containing date and time information |
| 28 | #[derive(Clone, Debug)] | ||
| 28 | pub struct DateTime { | 29 | pub struct DateTime { |
| 29 | /// 0..4095 | 30 | /// 0..4095 |
| 30 | pub year: u16, | 31 | pub year: u16, |
diff --git a/embassy-rp/src/rtc/mod.rs b/embassy-rp/src/rtc/mod.rs index b18f12fc4..1b33fdf8d 100644 --- a/embassy-rp/src/rtc/mod.rs +++ b/embassy-rp/src/rtc/mod.rs | |||
| @@ -12,26 +12,24 @@ pub use self::datetime::{DateTime, DayOfWeek, Error as DateTimeError}; | |||
| 12 | use crate::clocks::clk_rtc_freq; | 12 | use crate::clocks::clk_rtc_freq; |
| 13 | 13 | ||
| 14 | /// A reference to the real time clock of the system | 14 | /// A reference to the real time clock of the system |
| 15 | pub struct RealTimeClock<'d, T: Instance> { | 15 | pub struct Rtc<'d, T: Instance> { |
| 16 | inner: PeripheralRef<'d, T>, | 16 | inner: PeripheralRef<'d, T>, |
| 17 | } | 17 | } |
| 18 | 18 | ||
| 19 | impl<'d, T: Instance> RealTimeClock<'d, T> { | 19 | impl<'d, T: Instance> Rtc<'d, T> { |
| 20 | /// Create a new instance of the real time clock, with the given date as an initial value. | 20 | /// Create a new instance of the real time clock, with the given date as an initial value. |
| 21 | /// | 21 | /// |
| 22 | /// # Errors | 22 | /// # Errors |
| 23 | /// | 23 | /// |
| 24 | /// Will return `RtcError::InvalidDateTime` if the datetime is not a valid range. | 24 | /// Will return `RtcError::InvalidDateTime` if the datetime is not a valid range. |
| 25 | pub fn new(inner: impl Peripheral<P = T> + 'd, initial_date: DateTime) -> Result<Self, RtcError> { | 25 | pub fn new(inner: impl Peripheral<P = T> + 'd) -> Self { |
| 26 | into_ref!(inner); | 26 | into_ref!(inner); |
| 27 | 27 | ||
| 28 | // Set the RTC divider | 28 | // Set the RTC divider |
| 29 | inner.regs().clkdiv_m1().write(|w| w.set_clkdiv_m1(clk_rtc_freq() - 1)); | 29 | inner.regs().clkdiv_m1().write(|w| w.set_clkdiv_m1(clk_rtc_freq() - 1)); |
| 30 | 30 | ||
| 31 | let mut result = Self { inner }; | 31 | let result = Self { inner }; |
| 32 | result.set_leap_year_check(true); // should be on by default, make sure this is the case. | 32 | result |
| 33 | result.set_datetime(initial_date)?; | ||
| 34 | Ok(result) | ||
| 35 | } | 33 | } |
| 36 | 34 | ||
| 37 | /// Enable or disable the leap year check. The rp2040 chip will always add a Feb 29th on every year that is divisable by 4, but this may be incorrect (e.g. on century years). This function allows you to disable this check. | 35 | /// Enable or disable the leap year check. The rp2040 chip will always add a Feb 29th on every year that is divisable by 4, but this may be incorrect (e.g. on century years). This function allows you to disable this check. |
| @@ -43,7 +41,37 @@ impl<'d, T: Instance> RealTimeClock<'d, T> { | |||
| 43 | }); | 41 | }); |
| 44 | } | 42 | } |
| 45 | 43 | ||
| 46 | /// Checks to see if this RealTimeClock is running | 44 | /// Set the time from internal format |
| 45 | pub fn restore(&mut self, ymd: rp_pac::rtc::regs::Rtc1, hms: rp_pac::rtc::regs::Rtc0) { | ||
| 46 | // disable RTC while we configure it | ||
| 47 | self.inner.regs().ctrl().modify(|w| w.set_rtc_enable(false)); | ||
| 48 | while self.inner.regs().ctrl().read().rtc_active() { | ||
| 49 | core::hint::spin_loop(); | ||
| 50 | } | ||
| 51 | |||
| 52 | self.inner.regs().setup_0().write(|w| { | ||
| 53 | *w = rp_pac::rtc::regs::Setup0(ymd.0); | ||
| 54 | }); | ||
| 55 | self.inner.regs().setup_1().write(|w| { | ||
| 56 | *w = rp_pac::rtc::regs::Setup1(hms.0); | ||
| 57 | }); | ||
| 58 | |||
| 59 | // Load the new datetime and re-enable RTC | ||
| 60 | self.inner.regs().ctrl().write(|w| w.set_load(true)); | ||
| 61 | self.inner.regs().ctrl().write(|w| w.set_rtc_enable(true)); | ||
| 62 | while !self.inner.regs().ctrl().read().rtc_active() { | ||
| 63 | core::hint::spin_loop(); | ||
| 64 | } | ||
| 65 | } | ||
| 66 | |||
| 67 | /// Get the time in internal format | ||
| 68 | pub fn save(&mut self) -> (rp_pac::rtc::regs::Rtc1, rp_pac::rtc::regs::Rtc0) { | ||
| 69 | let rtc_0: rp_pac::rtc::regs::Rtc0 = self.inner.regs().rtc_0().read(); | ||
| 70 | let rtc_1 = self.inner.regs().rtc_1().read(); | ||
| 71 | (rtc_1, rtc_0) | ||
| 72 | } | ||
| 73 | |||
| 74 | /// Checks to see if this Rtc is running | ||
| 47 | pub fn is_running(&self) -> bool { | 75 | pub fn is_running(&self) -> bool { |
| 48 | self.inner.regs().ctrl().read().rtc_active() | 76 | self.inner.regs().ctrl().read().rtc_active() |
| 49 | } | 77 | } |
| @@ -113,8 +141,8 @@ impl<'d, T: Instance> RealTimeClock<'d, T> { | |||
| 113 | /// # fn main() { } | 141 | /// # fn main() { } |
| 114 | /// # #[cfg(not(feature = "chrono"))] | 142 | /// # #[cfg(not(feature = "chrono"))] |
| 115 | /// # fn main() { | 143 | /// # fn main() { |
| 116 | /// # use embassy_rp::rtc::{RealTimeClock, DateTimeFilter}; | 144 | /// # use embassy_rp::rtc::{Rtc, DateTimeFilter}; |
| 117 | /// # let mut real_time_clock: RealTimeClock<embassy_rp::peripherals::RTC> = unsafe { core::mem::zeroed() }; | 145 | /// # let mut real_time_clock: Rtc<embassy_rp::peripherals::RTC> = unsafe { core::mem::zeroed() }; |
| 118 | /// let now = real_time_clock.now().unwrap(); | 146 | /// let now = real_time_clock.now().unwrap(); |
| 119 | /// real_time_clock.schedule_alarm( | 147 | /// real_time_clock.schedule_alarm( |
| 120 | /// DateTimeFilter::default() | 148 | /// DateTimeFilter::default() |
| @@ -150,7 +178,7 @@ impl<'d, T: Instance> RealTimeClock<'d, T> { | |||
| 150 | } | 178 | } |
| 151 | } | 179 | } |
| 152 | 180 | ||
| 153 | /// Errors that can occur on methods on [RealTimeClock] | 181 | /// Errors that can occur on methods on [Rtc] |
| 154 | #[derive(Clone, Debug, PartialEq, Eq)] | 182 | #[derive(Clone, Debug, PartialEq, Eq)] |
| 155 | pub enum RtcError { | 183 | pub enum RtcError { |
| 156 | /// An invalid DateTime was given or stored on the hardware. | 184 | /// An invalid DateTime was given or stored on the hardware. |
diff --git a/embassy-rp/src/spi.rs b/embassy-rp/src/spi.rs index e817d074e..af101cf4a 100644 --- a/embassy-rp/src/spi.rs +++ b/embassy-rp/src/spi.rs | |||
| @@ -545,25 +545,19 @@ mod eh1 { | |||
| 545 | type Error = Error; | 545 | type Error = Error; |
| 546 | } | 546 | } |
| 547 | 547 | ||
| 548 | impl<'d, T: Instance, M: Mode> embedded_hal_1::spi::SpiBusFlush for Spi<'d, T, M> { | 548 | impl<'d, T: Instance, M: Mode> embedded_hal_1::spi::SpiBus<u8> for Spi<'d, T, M> { |
| 549 | fn flush(&mut self) -> Result<(), Self::Error> { | 549 | fn flush(&mut self) -> Result<(), Self::Error> { |
| 550 | Ok(()) | 550 | Ok(()) |
| 551 | } | 551 | } |
| 552 | } | ||
| 553 | 552 | ||
| 554 | impl<'d, T: Instance, M: Mode> embedded_hal_1::spi::SpiBusRead<u8> for Spi<'d, T, M> { | ||
| 555 | fn read(&mut self, words: &mut [u8]) -> Result<(), Self::Error> { | 553 | fn read(&mut self, words: &mut [u8]) -> Result<(), Self::Error> { |
| 556 | self.blocking_transfer(words, &[]) | 554 | self.blocking_transfer(words, &[]) |
| 557 | } | 555 | } |
| 558 | } | ||
| 559 | 556 | ||
| 560 | impl<'d, T: Instance, M: Mode> embedded_hal_1::spi::SpiBusWrite<u8> for Spi<'d, T, M> { | ||
| 561 | fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> { | 557 | fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> { |
| 562 | self.blocking_write(words) | 558 | self.blocking_write(words) |
| 563 | } | 559 | } |
| 564 | } | ||
| 565 | 560 | ||
| 566 | impl<'d, T: Instance, M: Mode> embedded_hal_1::spi::SpiBus<u8> for Spi<'d, T, M> { | ||
| 567 | fn transfer(&mut self, read: &mut [u8], write: &[u8]) -> Result<(), Self::Error> { | 561 | fn transfer(&mut self, read: &mut [u8], write: &[u8]) -> Result<(), Self::Error> { |
| 568 | self.blocking_transfer(read, write) | 562 | self.blocking_transfer(read, write) |
| 569 | } | 563 | } |
| @@ -578,30 +572,24 @@ mod eh1 { | |||
| 578 | mod eha { | 572 | mod eha { |
| 579 | use super::*; | 573 | use super::*; |
| 580 | 574 | ||
| 581 | impl<'d, T: Instance> embedded_hal_async::spi::SpiBusFlush for Spi<'d, T, Async> { | 575 | impl<'d, T: Instance> embedded_hal_async::spi::SpiBus<u8> for Spi<'d, T, Async> { |
| 582 | async fn flush(&mut self) -> Result<(), Self::Error> { | 576 | async fn flush(&mut self) -> Result<(), Self::Error> { |
| 583 | Ok(()) | 577 | Ok(()) |
| 584 | } | 578 | } |
| 585 | } | ||
| 586 | 579 | ||
| 587 | impl<'d, T: Instance> embedded_hal_async::spi::SpiBusWrite<u8> for Spi<'d, T, Async> { | ||
| 588 | async fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> { | 580 | async fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> { |
| 589 | self.write(words).await | 581 | self.write(words).await |
| 590 | } | 582 | } |
| 591 | } | ||
| 592 | 583 | ||
| 593 | impl<'d, T: Instance> embedded_hal_async::spi::SpiBusRead<u8> for Spi<'d, T, Async> { | ||
| 594 | async fn read(&mut self, words: &mut [u8]) -> Result<(), Self::Error> { | 584 | async fn read(&mut self, words: &mut [u8]) -> Result<(), Self::Error> { |
| 595 | self.read(words).await | 585 | self.read(words).await |
| 596 | } | 586 | } |
| 597 | } | ||
| 598 | 587 | ||
| 599 | impl<'d, T: Instance> embedded_hal_async::spi::SpiBus<u8> for Spi<'d, T, Async> { | 588 | async fn transfer(&mut self, read: &mut [u8], write: &[u8]) -> Result<(), Self::Error> { |
| 600 | async fn transfer<'a>(&'a mut self, read: &'a mut [u8], write: &'a [u8]) -> Result<(), Self::Error> { | ||
| 601 | self.transfer(read, write).await | 589 | self.transfer(read, write).await |
| 602 | } | 590 | } |
| 603 | 591 | ||
| 604 | async fn transfer_in_place<'a>(&'a mut self, words: &'a mut [u8]) -> Result<(), Self::Error> { | 592 | async fn transfer_in_place(&mut self, words: &mut [u8]) -> Result<(), Self::Error> { |
| 605 | self.transfer_in_place(words).await | 593 | self.transfer_in_place(words).await |
| 606 | } | 594 | } |
| 607 | } | 595 | } |
diff --git a/embassy-rp/src/usb.rs b/embassy-rp/src/usb.rs index b3f3bd927..4ab881f6e 100644 --- a/embassy-rp/src/usb.rs +++ b/embassy-rp/src/usb.rs | |||
| @@ -361,6 +361,7 @@ impl<'d, T: Instance> driver::Bus for Bus<'d, T> { | |||
| 361 | 361 | ||
| 362 | let regs = T::regs(); | 362 | let regs = T::regs(); |
| 363 | let siestatus = regs.sie_status().read(); | 363 | let siestatus = regs.sie_status().read(); |
| 364 | let intrstatus = regs.intr().read(); | ||
| 364 | 365 | ||
| 365 | if siestatus.resume() { | 366 | if siestatus.resume() { |
| 366 | regs.sie_status().write(|w| w.set_resume(true)); | 367 | regs.sie_status().write(|w| w.set_resume(true)); |
| @@ -389,7 +390,7 @@ impl<'d, T: Instance> driver::Bus for Bus<'d, T> { | |||
| 389 | return Poll::Ready(Event::Reset); | 390 | return Poll::Ready(Event::Reset); |
| 390 | } | 391 | } |
| 391 | 392 | ||
| 392 | if siestatus.suspended() { | 393 | if siestatus.suspended() && intrstatus.dev_suspend() { |
| 393 | regs.sie_status().write(|w| w.set_suspended(true)); | 394 | regs.sie_status().write(|w| w.set_suspended(true)); |
| 394 | return Poll::Ready(Event::Suspend); | 395 | return Poll::Ready(Event::Suspend); |
| 395 | } | 396 | } |
diff --git a/embassy-rp/src/watchdog.rs b/embassy-rp/src/watchdog.rs index d37795cc9..f1e986ec7 100644 --- a/embassy-rp/src/watchdog.rs +++ b/embassy-rp/src/watchdog.rs | |||
| @@ -107,4 +107,36 @@ impl Watchdog { | |||
| 107 | w.set_trigger(true); | 107 | w.set_trigger(true); |
| 108 | }) | 108 | }) |
| 109 | } | 109 | } |
| 110 | |||
| 111 | /// Store data in scratch register | ||
| 112 | pub fn set_scratch(&mut self, index: usize, value: u32) { | ||
| 113 | let watchdog = pac::WATCHDOG; | ||
| 114 | match index { | ||
| 115 | 0 => watchdog.scratch0().write(|w| *w = value), | ||
| 116 | 1 => watchdog.scratch1().write(|w| *w = value), | ||
| 117 | 2 => watchdog.scratch2().write(|w| *w = value), | ||
| 118 | 3 => watchdog.scratch3().write(|w| *w = value), | ||
| 119 | 4 => watchdog.scratch4().write(|w| *w = value), | ||
| 120 | 5 => watchdog.scratch5().write(|w| *w = value), | ||
| 121 | 6 => watchdog.scratch6().write(|w| *w = value), | ||
| 122 | 7 => watchdog.scratch7().write(|w| *w = value), | ||
| 123 | _ => panic!("Invalid watchdog scratch index"), | ||
| 124 | } | ||
| 125 | } | ||
| 126 | |||
| 127 | /// Read data from scratch register | ||
| 128 | pub fn get_scratch(&mut self, index: usize) -> u32 { | ||
| 129 | let watchdog = pac::WATCHDOG; | ||
| 130 | match index { | ||
| 131 | 0 => watchdog.scratch0().read(), | ||
| 132 | 1 => watchdog.scratch1().read(), | ||
| 133 | 2 => watchdog.scratch2().read(), | ||
| 134 | 3 => watchdog.scratch3().read(), | ||
| 135 | 4 => watchdog.scratch4().read(), | ||
| 136 | 5 => watchdog.scratch5().read(), | ||
| 137 | 6 => watchdog.scratch6().read(), | ||
| 138 | 7 => watchdog.scratch7().read(), | ||
| 139 | _ => panic!("Invalid watchdog scratch index"), | ||
| 140 | } | ||
| 141 | } | ||
| 110 | } | 142 | } |
diff --git a/embassy-stm32-wpan/Cargo.toml b/embassy-stm32-wpan/Cargo.toml index 4b830cab3..868bffe74 100644 --- a/embassy-stm32-wpan/Cargo.toml +++ b/embassy-stm32-wpan/Cargo.toml | |||
| @@ -5,15 +5,15 @@ edition = "2021" | |||
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
| 6 | 6 | ||
| 7 | [package.metadata.embassy_docs] | 7 | [package.metadata.embassy_docs] |
| 8 | src_base = "https://github.com/embassy-rs/embassy/blob/embassy-stm32-wpan-v$VERSION/embassy-stm32-wpan/src" | 8 | src_base = "https://github.com/embassy-rs/embassy/blob/embassy-stm32-wpan-v$VERSION/embassy-stm32-wpan/src/" |
| 9 | src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-stm32-wpan/src" | 9 | src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-stm32-wpan/src/" |
| 10 | target = "thumbv7em-none-eabihf" | 10 | target = "thumbv7em-none-eabihf" |
| 11 | features = ["stm32wb55rg"] | 11 | features = ["stm32wb55rg"] |
| 12 | 12 | ||
| 13 | [dependencies] | 13 | [dependencies] |
| 14 | embassy-stm32 = { version = "0.1.0", path = "../embassy-stm32" } | 14 | embassy-stm32 = { version = "0.1.0", path = "../embassy-stm32" } |
| 15 | embassy-sync = { version = "0.2.0", path = "../embassy-sync" } | 15 | embassy-sync = { version = "0.2.0", path = "../embassy-sync" } |
| 16 | embassy-time = { version = "0.1.0", path = "../embassy-time", optional = true } | 16 | embassy-time = { version = "0.1.2", path = "../embassy-time", optional = true } |
| 17 | embassy-futures = { version = "0.1.0", path = "../embassy-futures" } | 17 | embassy-futures = { version = "0.1.0", path = "../embassy-futures" } |
| 18 | embassy-hal-common = { version = "0.1.0", path = "../embassy-hal-common" } | 18 | embassy-hal-common = { version = "0.1.0", path = "../embassy-hal-common" } |
| 19 | embassy-embedded-hal = { version = "0.1.0", path = "../embassy-embedded-hal" } | 19 | embassy-embedded-hal = { version = "0.1.0", path = "../embassy-embedded-hal" } |
| @@ -25,13 +25,14 @@ aligned = "0.4.1" | |||
| 25 | 25 | ||
| 26 | bit_field = "0.10.2" | 26 | bit_field = "0.10.2" |
| 27 | stm32-device-signature = { version = "0.3.3", features = ["stm32wb5x"] } | 27 | stm32-device-signature = { version = "0.3.3", features = ["stm32wb5x"] } |
| 28 | stm32wb-hci = { version = "0.1.2", features = ["version-5-0"], optional = true } | 28 | stm32wb-hci = { version = "0.1.3", optional = true } |
| 29 | bitflags = { version = "2.3.3", optional = true } | ||
| 29 | 30 | ||
| 30 | [features] | 31 | [features] |
| 31 | defmt = ["dep:defmt", "embassy-sync/defmt", "embassy-embedded-hal/defmt", "embassy-hal-common/defmt"] | 32 | defmt = ["dep:defmt", "embassy-sync/defmt", "embassy-embedded-hal/defmt", "embassy-hal-common/defmt", "stm32wb-hci?/defmt"] |
| 32 | 33 | ||
| 33 | ble = ["dep:stm32wb-hci"] | 34 | ble = ["dep:stm32wb-hci"] |
| 34 | mac = [] | 35 | mac = ["dep:bitflags"] |
| 35 | 36 | ||
| 36 | stm32wb10cc = [ "embassy-stm32/stm32wb10cc" ] | 37 | stm32wb10cc = [ "embassy-stm32/stm32wb10cc" ] |
| 37 | stm32wb15cc = [ "embassy-stm32/stm32wb15cc" ] | 38 | stm32wb15cc = [ "embassy-stm32/stm32wb15cc" ] |
| @@ -48,4 +49,4 @@ stm32wb55rg = [ "embassy-stm32/stm32wb55rg" ] | |||
| 48 | stm32wb55vc = [ "embassy-stm32/stm32wb55vc" ] | 49 | stm32wb55vc = [ "embassy-stm32/stm32wb55vc" ] |
| 49 | stm32wb55ve = [ "embassy-stm32/stm32wb55ve" ] | 50 | stm32wb55ve = [ "embassy-stm32/stm32wb55ve" ] |
| 50 | stm32wb55vg = [ "embassy-stm32/stm32wb55vg" ] | 51 | stm32wb55vg = [ "embassy-stm32/stm32wb55vg" ] |
| 51 | stm32wb55vy = [ "embassy-stm32/stm32wb55vy" ] \ No newline at end of file | 52 | stm32wb55vy = [ "embassy-stm32/stm32wb55vy" ] |
diff --git a/embassy-stm32-wpan/src/cmd.rs b/embassy-stm32-wpan/src/cmd.rs index 8428b6ffc..928357384 100644 --- a/embassy-stm32-wpan/src/cmd.rs +++ b/embassy-stm32-wpan/src/cmd.rs | |||
| @@ -37,7 +37,7 @@ pub struct CmdSerialStub { | |||
| 37 | } | 37 | } |
| 38 | 38 | ||
| 39 | #[derive(Copy, Clone, Default)] | 39 | #[derive(Copy, Clone, Default)] |
| 40 | #[repr(C, packed(4))] | 40 | #[repr(C, packed)] |
| 41 | pub struct CmdPacket { | 41 | pub struct CmdPacket { |
| 42 | pub header: PacketHeader, | 42 | pub header: PacketHeader, |
| 43 | pub cmdserial: CmdSerial, | 43 | pub cmdserial: CmdSerial, |
diff --git a/embassy-stm32-wpan/src/consts.rs b/embassy-stm32-wpan/src/consts.rs index f234151d7..bd70851ea 100644 --- a/embassy-stm32-wpan/src/consts.rs +++ b/embassy-stm32-wpan/src/consts.rs | |||
| @@ -6,6 +6,8 @@ use crate::PacketHeader; | |||
| 6 | #[derive(Debug)] | 6 | #[derive(Debug)] |
| 7 | #[repr(C)] | 7 | #[repr(C)] |
| 8 | pub enum TlPacketType { | 8 | pub enum TlPacketType { |
| 9 | MacCmd = 0x00, | ||
| 10 | |||
| 9 | BleCmd = 0x01, | 11 | BleCmd = 0x01, |
| 10 | AclData = 0x02, | 12 | AclData = 0x02, |
| 11 | BleEvt = 0x04, | 13 | BleEvt = 0x04, |
| @@ -79,6 +81,7 @@ pub const CFG_TL_BLE_MOST_EVENT_PAYLOAD_SIZE: usize = 255; | |||
| 79 | pub const TL_BLE_EVENT_FRAME_SIZE: usize = TL_EVT_HEADER_SIZE + CFG_TL_BLE_MOST_EVENT_PAYLOAD_SIZE; | 81 | pub const TL_BLE_EVENT_FRAME_SIZE: usize = TL_EVT_HEADER_SIZE + CFG_TL_BLE_MOST_EVENT_PAYLOAD_SIZE; |
| 80 | 82 | ||
| 81 | pub const POOL_SIZE: usize = CFG_TL_BLE_EVT_QUEUE_LENGTH * 4 * divc(TL_PACKET_HEADER_SIZE + TL_BLE_EVENT_FRAME_SIZE, 4); | 83 | pub const POOL_SIZE: usize = CFG_TL_BLE_EVT_QUEUE_LENGTH * 4 * divc(TL_PACKET_HEADER_SIZE + TL_BLE_EVENT_FRAME_SIZE, 4); |
| 84 | pub const C_SIZE_CMD_STRING: usize = 256; | ||
| 82 | 85 | ||
| 83 | pub const fn divc(x: usize, y: usize) -> usize { | 86 | pub const fn divc(x: usize, y: usize) -> usize { |
| 84 | (x + y - 1) / y | 87 | (x + y - 1) / y |
diff --git a/embassy-stm32-wpan/src/lib.rs b/embassy-stm32-wpan/src/lib.rs index 99c610583..57f0dc4fa 100644 --- a/embassy-stm32-wpan/src/lib.rs +++ b/embassy-stm32-wpan/src/lib.rs | |||
| @@ -26,6 +26,9 @@ pub mod sub; | |||
| 26 | pub mod tables; | 26 | pub mod tables; |
| 27 | pub mod unsafe_linked_list; | 27 | pub mod unsafe_linked_list; |
| 28 | 28 | ||
| 29 | #[cfg(feature = "mac")] | ||
| 30 | pub mod mac; | ||
| 31 | |||
| 29 | #[cfg(feature = "ble")] | 32 | #[cfg(feature = "ble")] |
| 30 | pub use crate::sub::ble::hci; | 33 | pub use crate::sub::ble::hci; |
| 31 | 34 | ||
| @@ -60,9 +63,9 @@ impl<'d> TlMbox<'d> { | |||
| 60 | mem_manager_table: TL_MEM_MANAGER_TABLE.as_ptr(), | 63 | mem_manager_table: TL_MEM_MANAGER_TABLE.as_ptr(), |
| 61 | traces_table: TL_TRACES_TABLE.as_ptr(), | 64 | traces_table: TL_TRACES_TABLE.as_ptr(), |
| 62 | mac_802_15_4_table: TL_MAC_802_15_4_TABLE.as_ptr(), | 65 | mac_802_15_4_table: TL_MAC_802_15_4_TABLE.as_ptr(), |
| 63 | // zigbee_table: TL_ZIGBEE_TABLE.as_ptr(), | 66 | zigbee_table: TL_ZIGBEE_TABLE.as_ptr(), |
| 64 | // lld_tests_table: TL_LLD_TESTS_TABLE.as_ptr(), | 67 | lld_tests_table: TL_LLD_TESTS_TABLE.as_ptr(), |
| 65 | // ble_lld_table: TL_BLE_LLD_TABLE.as_ptr(), | 68 | ble_lld_table: TL_BLE_LLD_TABLE.as_ptr(), |
| 66 | }); | 69 | }); |
| 67 | 70 | ||
| 68 | TL_SYS_TABLE | 71 | TL_SYS_TABLE |
| @@ -87,15 +90,15 @@ impl<'d> TlMbox<'d> { | |||
| 87 | TL_MAC_802_15_4_TABLE | 90 | TL_MAC_802_15_4_TABLE |
| 88 | .as_mut_ptr() | 91 | .as_mut_ptr() |
| 89 | .write_volatile(MaybeUninit::zeroed().assume_init()); | 92 | .write_volatile(MaybeUninit::zeroed().assume_init()); |
| 90 | // TL_ZIGBEE_TABLE | 93 | TL_ZIGBEE_TABLE |
| 91 | // .as_mut_ptr() | 94 | .as_mut_ptr() |
| 92 | // .write_volatile(MaybeUninit::zeroed().assume_init()); | 95 | .write_volatile(MaybeUninit::zeroed().assume_init()); |
| 93 | // TL_LLD_TESTS_TABLE | 96 | TL_LLD_TESTS_TABLE |
| 94 | // .as_mut_ptr() | 97 | .as_mut_ptr() |
| 95 | // .write_volatile(MaybeUninit::zeroed().assume_init()); | 98 | .write_volatile(MaybeUninit::zeroed().assume_init()); |
| 96 | // TL_BLE_LLD_TABLE | 99 | TL_BLE_LLD_TABLE |
| 97 | // .as_mut_ptr() | 100 | .as_mut_ptr() |
| 98 | // .write_volatile(MaybeUninit::zeroed().assume_init()); | 101 | .write_volatile(MaybeUninit::zeroed().assume_init()); |
| 99 | 102 | ||
| 100 | EVT_POOL | 103 | EVT_POOL |
| 101 | .as_mut_ptr() | 104 | .as_mut_ptr() |
| @@ -103,18 +106,30 @@ impl<'d> TlMbox<'d> { | |||
| 103 | SYS_SPARE_EVT_BUF | 106 | SYS_SPARE_EVT_BUF |
| 104 | .as_mut_ptr() | 107 | .as_mut_ptr() |
| 105 | .write_volatile(MaybeUninit::zeroed().assume_init()); | 108 | .write_volatile(MaybeUninit::zeroed().assume_init()); |
| 106 | BLE_SPARE_EVT_BUF | 109 | CS_BUFFER |
| 107 | .as_mut_ptr() | 110 | .as_mut_ptr() |
| 108 | .write_volatile(MaybeUninit::zeroed().assume_init()); | 111 | .write_volatile(MaybeUninit::zeroed().assume_init()); |
| 109 | 112 | ||
| 113 | #[cfg(feature = "ble")] | ||
| 110 | { | 114 | { |
| 115 | BLE_SPARE_EVT_BUF | ||
| 116 | .as_mut_ptr() | ||
| 117 | .write_volatile(MaybeUninit::zeroed().assume_init()); | ||
| 118 | |||
| 111 | BLE_CMD_BUFFER | 119 | BLE_CMD_BUFFER |
| 112 | .as_mut_ptr() | 120 | .as_mut_ptr() |
| 113 | .write_volatile(MaybeUninit::zeroed().assume_init()); | 121 | .write_volatile(MaybeUninit::zeroed().assume_init()); |
| 114 | HCI_ACL_DATA_BUFFER | 122 | HCI_ACL_DATA_BUFFER |
| 115 | .as_mut_ptr() | 123 | .as_mut_ptr() |
| 116 | .write_volatile(MaybeUninit::zeroed().assume_init()); | 124 | .write_volatile(MaybeUninit::zeroed().assume_init()); |
| 117 | CS_BUFFER | 125 | } |
| 126 | |||
| 127 | #[cfg(feature = "mac")] | ||
| 128 | { | ||
| 129 | MAC_802_15_4_CMD_BUFFER | ||
| 130 | .as_mut_ptr() | ||
| 131 | .write_volatile(MaybeUninit::zeroed().assume_init()); | ||
| 132 | MAC_802_15_4_NOTIF_RSP_EVT_BUFFER | ||
| 118 | .as_mut_ptr() | 133 | .as_mut_ptr() |
| 119 | .write_volatile(MaybeUninit::zeroed().assume_init()); | 134 | .write_volatile(MaybeUninit::zeroed().assume_init()); |
| 120 | } | 135 | } |
diff --git a/embassy-stm32-wpan/src/mac/commands.rs b/embassy-stm32-wpan/src/mac/commands.rs new file mode 100644 index 000000000..8cfa0a054 --- /dev/null +++ b/embassy-stm32-wpan/src/mac/commands.rs | |||
| @@ -0,0 +1,467 @@ | |||
| 1 | use super::opcodes::OpcodeM4ToM0; | ||
| 2 | use super::typedefs::{ | ||
| 3 | AddressMode, Capabilities, DisassociationReason, GtsCharacteristics, KeyIdMode, MacAddress, MacChannel, MacStatus, | ||
| 4 | PanId, PibId, ScanType, SecurityLevel, | ||
| 5 | }; | ||
| 6 | |||
| 7 | pub trait MacCommand { | ||
| 8 | const OPCODE: OpcodeM4ToM0; | ||
| 9 | const SIZE: usize; | ||
| 10 | |||
| 11 | fn copy_into_slice(&self, buf: &mut [u8]) { | ||
| 12 | unsafe { core::ptr::copy(self as *const _ as *const u8, buf as *mut _ as *mut u8, Self::SIZE) }; | ||
| 13 | } | ||
| 14 | } | ||
| 15 | |||
| 16 | /// MLME ASSOCIATE Request used to request an association | ||
| 17 | #[repr(C)] | ||
| 18 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 19 | pub struct AssociateRequest { | ||
| 20 | /// the logical channel on which to attempt association | ||
| 21 | pub channel_number: MacChannel, | ||
| 22 | /// the channel page on which to attempt association | ||
| 23 | pub channel_page: u8, | ||
| 24 | /// coordinator addressing mode | ||
| 25 | pub coord_addr_mode: AddressMode, | ||
| 26 | /// operational capabilities of the associating device | ||
| 27 | pub capability_information: Capabilities, | ||
| 28 | /// the identifier of the PAN with which to associate | ||
| 29 | pub coord_pan_id: PanId, | ||
| 30 | /// the security level to be used | ||
| 31 | pub security_level: SecurityLevel, | ||
| 32 | /// the mode used to identify the key to be used | ||
| 33 | pub key_id_mode: KeyIdMode, | ||
| 34 | /// the originator of the key to be used | ||
| 35 | pub key_source: [u8; 8], | ||
| 36 | /// Coordinator address | ||
| 37 | pub coord_address: MacAddress, | ||
| 38 | /// the index of the key to be used | ||
| 39 | pub key_index: u8, | ||
| 40 | } | ||
| 41 | |||
| 42 | impl MacCommand for AssociateRequest { | ||
| 43 | const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeAssociateReq; | ||
| 44 | const SIZE: usize = 25; | ||
| 45 | } | ||
| 46 | |||
| 47 | /// MLME DISASSOCIATE Request sed to request a disassociation | ||
| 48 | #[repr(C)] | ||
| 49 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 50 | pub struct DisassociateRequest { | ||
| 51 | /// device addressing mode used | ||
| 52 | pub device_addr_mode: AddressMode, | ||
| 53 | /// the identifier of the PAN of the device | ||
| 54 | pub device_pan_id: PanId, | ||
| 55 | /// the reason for the disassociation | ||
| 56 | pub disassociation_reason: DisassociationReason, | ||
| 57 | /// device address | ||
| 58 | pub device_address: MacAddress, | ||
| 59 | /// `true` if the disassociation notification command is to be sent indirectly | ||
| 60 | pub tx_indirect: bool, | ||
| 61 | /// the security level to be used | ||
| 62 | pub security_level: SecurityLevel, | ||
| 63 | /// the mode to be used to indetify the key to be used | ||
| 64 | pub key_id_mode: KeyIdMode, | ||
| 65 | /// the index of the key to be used | ||
| 66 | pub key_index: u8, | ||
| 67 | /// the originator of the key to be used | ||
| 68 | pub key_source: [u8; 8], | ||
| 69 | } | ||
| 70 | |||
| 71 | impl MacCommand for DisassociateRequest { | ||
| 72 | const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeDisassociateReq; | ||
| 73 | const SIZE: usize = 24; | ||
| 74 | } | ||
| 75 | |||
| 76 | /// MLME GET Request used to request a PIB value | ||
| 77 | #[repr(C)] | ||
| 78 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 79 | pub struct GetRequest { | ||
| 80 | /// the name of the PIB attribute to read | ||
| 81 | pub pib_attribute: PibId, | ||
| 82 | } | ||
| 83 | |||
| 84 | impl MacCommand for GetRequest { | ||
| 85 | const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeGetReq; | ||
| 86 | const SIZE: usize = 4; | ||
| 87 | } | ||
| 88 | |||
| 89 | /// MLME GTS Request used to request and maintain GTSs | ||
| 90 | #[repr(C)] | ||
| 91 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 92 | pub struct GtsRequest { | ||
| 93 | /// the characteristics of the GTS | ||
| 94 | pub characteristics: GtsCharacteristics, | ||
| 95 | /// the security level to be used | ||
| 96 | pub security_level: SecurityLevel, | ||
| 97 | /// the mode used to identify the key to be used | ||
| 98 | pub key_id_mode: KeyIdMode, | ||
| 99 | /// the index of the key to be used | ||
| 100 | pub key_index: u8, | ||
| 101 | /// the originator of the key to be used | ||
| 102 | pub key_source: [u8; 8], | ||
| 103 | } | ||
| 104 | |||
| 105 | impl MacCommand for GtsRequest { | ||
| 106 | const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeGetReq; | ||
| 107 | const SIZE: usize = 12; | ||
| 108 | } | ||
| 109 | |||
| 110 | #[repr(C)] | ||
| 111 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 112 | pub struct ResetRequest { | ||
| 113 | /// MAC PIB attributes are set to their default values or not during reset | ||
| 114 | pub set_default_pib: bool, | ||
| 115 | } | ||
| 116 | |||
| 117 | impl MacCommand for ResetRequest { | ||
| 118 | const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeResetReq; | ||
| 119 | const SIZE: usize = 4; | ||
| 120 | } | ||
| 121 | |||
| 122 | /// MLME RX ENABLE Request used to request that the receiver is either enabled | ||
| 123 | /// for a finite period of time or disabled | ||
| 124 | #[repr(C)] | ||
| 125 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 126 | pub struct RxEnableRequest { | ||
| 127 | /// the request operation can be deferred or not | ||
| 128 | pub defer_permit: bool, | ||
| 129 | /// configure the transceiver to RX with ranging for a value of | ||
| 130 | /// RANGING_ON or to not enable ranging for RANGING_OFF | ||
| 131 | pub ranging_rx_control: u8, | ||
| 132 | /// number of symbols measured before the receiver is to be enabled or disabled | ||
| 133 | pub rx_on_time: [u8; 4], | ||
| 134 | /// number of symbols for which the receiver is to be enabled | ||
| 135 | pub rx_on_duration: [u8; 4], | ||
| 136 | } | ||
| 137 | |||
| 138 | impl MacCommand for RxEnableRequest { | ||
| 139 | const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeRxEnableReq; | ||
| 140 | const SIZE: usize = 12; | ||
| 141 | |||
| 142 | fn copy_into_slice(&self, buf: &mut [u8]) { | ||
| 143 | buf[0] = self.defer_permit as u8; | ||
| 144 | buf[1] = self.ranging_rx_control as u8; | ||
| 145 | |||
| 146 | // stuffing to keep 32bit alignment | ||
| 147 | buf[2] = 0; | ||
| 148 | buf[3] = 0; | ||
| 149 | |||
| 150 | buf[4..8].copy_from_slice(&self.rx_on_time); | ||
| 151 | buf[8..12].copy_from_slice(&self.rx_on_duration); | ||
| 152 | } | ||
| 153 | } | ||
| 154 | |||
| 155 | /// MLME SCAN Request used to initiate a channel scan over a given list of channels | ||
| 156 | #[repr(C)] | ||
| 157 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 158 | pub struct ScanRequest { | ||
| 159 | /// the type of scan to be performed | ||
| 160 | pub scan_type: ScanType, | ||
| 161 | /// the time spent on scanning each channel | ||
| 162 | pub scan_duration: u8, | ||
| 163 | /// channel page on which to perform the scan | ||
| 164 | pub channel_page: u8, | ||
| 165 | /// security level to be used | ||
| 166 | pub security_level: SecurityLevel, | ||
| 167 | /// indicate which channels are to be scanned | ||
| 168 | pub scan_channels: [u8; 4], | ||
| 169 | /// originator the key to be used | ||
| 170 | pub key_source: [u8; 8], | ||
| 171 | /// mode used to identify the key to be used | ||
| 172 | pub key_id_mode: KeyIdMode, | ||
| 173 | /// index of the key to be used | ||
| 174 | pub key_index: u8, | ||
| 175 | } | ||
| 176 | |||
| 177 | impl MacCommand for ScanRequest { | ||
| 178 | const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeScanReq; | ||
| 179 | const SIZE: usize = 20; | ||
| 180 | } | ||
| 181 | |||
| 182 | /// MLME SET Request used to attempt to write the given value to the indicated PIB attribute | ||
| 183 | #[repr(C)] | ||
| 184 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 185 | pub struct SetRequest { | ||
| 186 | /// the pointer to the value of the PIB attribute to set | ||
| 187 | pub pib_attribute_ptr: *const u8, | ||
| 188 | /// the name of the PIB attribute to set | ||
| 189 | pub pib_attribute: PibId, | ||
| 190 | } | ||
| 191 | |||
| 192 | impl MacCommand for SetRequest { | ||
| 193 | const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeSetReq; | ||
| 194 | const SIZE: usize = 8; | ||
| 195 | } | ||
| 196 | |||
| 197 | /// MLME START Request used by the FFDs to intiate a new PAN or to begin using a new superframe | ||
| 198 | /// configuration | ||
| 199 | #[derive(Default)] | ||
| 200 | #[repr(C)] | ||
| 201 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 202 | pub struct StartRequest { | ||
| 203 | /// PAN indentifier to used by the device | ||
| 204 | pub pan_id: PanId, | ||
| 205 | /// logical channel on which to begin | ||
| 206 | pub channel_number: MacChannel, | ||
| 207 | /// channel page on which to begin | ||
| 208 | pub channel_page: u8, | ||
| 209 | /// time at which to begin transmitting beacons | ||
| 210 | pub start_time: [u8; 4], | ||
| 211 | /// indicated how often the beacon is to be transmitted | ||
| 212 | pub beacon_order: u8, | ||
| 213 | /// length of the active portion of the superframe | ||
| 214 | pub superframe_order: u8, | ||
| 215 | /// indicated wheter the device is a PAN coordinator or not | ||
| 216 | pub pan_coordinator: bool, | ||
| 217 | /// indicates if the receiver of the beaconing device is disabled or not | ||
| 218 | pub battery_life_extension: bool, | ||
| 219 | /// indicated if the coordinator realignment command is to be trasmitted | ||
| 220 | pub coord_realignment: u8, | ||
| 221 | /// indicated if the coordinator realignment command is to be trasmitted | ||
| 222 | pub coord_realign_security_level: SecurityLevel, | ||
| 223 | /// index of the key to be used | ||
| 224 | pub coord_realign_key_id_index: u8, | ||
| 225 | /// originator of the key to be used | ||
| 226 | pub coord_realign_key_source: [u8; 8], | ||
| 227 | /// security level to be used for beacon frames | ||
| 228 | pub beacon_security_level: SecurityLevel, | ||
| 229 | /// mode used to identify the key to be used | ||
| 230 | pub beacon_key_id_mode: KeyIdMode, | ||
| 231 | /// index of the key to be used | ||
| 232 | pub beacon_key_index: u8, | ||
| 233 | /// originator of the key to be used | ||
| 234 | pub beacon_key_source: [u8; 8], | ||
| 235 | } | ||
| 236 | |||
| 237 | impl MacCommand for StartRequest { | ||
| 238 | const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeStartReq; | ||
| 239 | const SIZE: usize = 35; | ||
| 240 | } | ||
| 241 | |||
| 242 | /// MLME SYNC Request used to synchronize with the coordinator by acquiring and, if | ||
| 243 | /// specified, tracking its beacons | ||
| 244 | #[repr(C)] | ||
| 245 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 246 | pub struct SyncRequest { | ||
| 247 | /// the channel number on which to attempt coordinator synchronization | ||
| 248 | pub channel_number: MacChannel, | ||
| 249 | /// the channel page on which to attempt coordinator synchronization | ||
| 250 | pub channel_page: u8, | ||
| 251 | /// `true` if the MLME is to synchronize with the next beacon and attempts | ||
| 252 | /// to track all future beacons. | ||
| 253 | /// | ||
| 254 | /// `false` if the MLME is to synchronize with only the next beacon | ||
| 255 | pub track_beacon: bool, | ||
| 256 | } | ||
| 257 | |||
| 258 | impl MacCommand for SyncRequest { | ||
| 259 | const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeSyncReq; | ||
| 260 | const SIZE: usize = 4; | ||
| 261 | } | ||
| 262 | |||
| 263 | /// MLME POLL Request propmts the device to request data from the coordinator | ||
| 264 | #[repr(C)] | ||
| 265 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 266 | pub struct PollRequest { | ||
| 267 | /// addressing mode of the coordinator | ||
| 268 | pub coord_addr_mode: AddressMode, | ||
| 269 | /// security level to be used | ||
| 270 | pub security_level: SecurityLevel, | ||
| 271 | /// mode used to identify the key to be used | ||
| 272 | pub key_id_mode: KeyIdMode, | ||
| 273 | /// index of the key to be used | ||
| 274 | pub key_index: u8, | ||
| 275 | /// coordinator address | ||
| 276 | pub coord_address: MacAddress, | ||
| 277 | /// originator of the key to be used | ||
| 278 | pub key_source: [u8; 8], | ||
| 279 | /// PAN identifier of the coordinator | ||
| 280 | pub coord_pan_id: PanId, | ||
| 281 | } | ||
| 282 | |||
| 283 | impl MacCommand for PollRequest { | ||
| 284 | const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmePollReq; | ||
| 285 | const SIZE: usize = 24; | ||
| 286 | } | ||
| 287 | |||
| 288 | /// MLME DPS Request allows the next higher layer to request that the PHY utilize a | ||
| 289 | /// given pair of preamble codes for a single use pending expiration of the DPSIndexDuration | ||
| 290 | #[repr(C)] | ||
| 291 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 292 | pub struct DpsRequest { | ||
| 293 | /// the index value for the transmitter | ||
| 294 | tx_dps_index: u8, | ||
| 295 | /// the index value of the receiver | ||
| 296 | rx_dps_index: u8, | ||
| 297 | /// the number of symbols for which the transmitter and receiver will utilize the | ||
| 298 | /// respective DPS indices | ||
| 299 | dps_index_duration: u8, | ||
| 300 | } | ||
| 301 | |||
| 302 | impl MacCommand for DpsRequest { | ||
| 303 | const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeDpsReq; | ||
| 304 | const SIZE: usize = 4; | ||
| 305 | } | ||
| 306 | |||
| 307 | /// MLME SOUNDING request primitive which is used by the next higher layer to request that | ||
| 308 | /// the PHY respond with channel sounding information | ||
| 309 | #[repr(C)] | ||
| 310 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 311 | pub struct SoundingRequest; | ||
| 312 | |||
| 313 | impl MacCommand for SoundingRequest { | ||
| 314 | const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeSoundingReq; | ||
| 315 | const SIZE: usize = 4; | ||
| 316 | } | ||
| 317 | |||
| 318 | /// MLME CALIBRATE request primitive which used to obtain the results of a ranging | ||
| 319 | /// calibration request from an RDEV | ||
| 320 | #[repr(C)] | ||
| 321 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 322 | pub struct CalibrateRequest; | ||
| 323 | |||
| 324 | impl MacCommand for CalibrateRequest { | ||
| 325 | const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeCalibrateReq; | ||
| 326 | const SIZE: usize = 4; | ||
| 327 | } | ||
| 328 | |||
| 329 | /// MCPS DATA Request used for MAC data related requests from the application | ||
| 330 | #[repr(C)] | ||
| 331 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 332 | pub struct DataRequest { | ||
| 333 | /// the handle assocated with the MSDU to be transmitted | ||
| 334 | pub msdu_ptr: *const u8, | ||
| 335 | /// source addressing mode used | ||
| 336 | pub src_addr_mode: AddressMode, | ||
| 337 | /// destination addressing mode used | ||
| 338 | pub dst_addr_mode: AddressMode, | ||
| 339 | /// destination PAN Id | ||
| 340 | pub dst_pan_id: PanId, | ||
| 341 | /// destination address | ||
| 342 | pub dst_address: MacAddress, | ||
| 343 | /// the number of octets contained in the MSDU | ||
| 344 | pub msdu_length: u8, | ||
| 345 | /// the handle assocated with the MSDU to be transmitted | ||
| 346 | pub msdu_handle: u8, | ||
| 347 | /// the ACK transmittion options for the MSDU | ||
| 348 | pub ack_tx: u8, | ||
| 349 | /// `true` if a GTS is to be used for transmission | ||
| 350 | /// | ||
| 351 | /// `false` indicates that the CAP will be used | ||
| 352 | pub gts_tx: bool, | ||
| 353 | /// the pending bit transmission options for the MSDU | ||
| 354 | pub indirect_tx: u8, | ||
| 355 | /// the security level to be used | ||
| 356 | pub security_level: SecurityLevel, | ||
| 357 | /// the mode used to indentify the key to be used | ||
| 358 | pub key_id_mode: KeyIdMode, | ||
| 359 | /// the index of the key to be used | ||
| 360 | pub key_index: u8, | ||
| 361 | /// the originator of the key to be used | ||
| 362 | pub key_source: [u8; 8], | ||
| 363 | /// 2011 - the pulse repitition value | ||
| 364 | pub uwbprf: u8, | ||
| 365 | /// 2011 - the ranging configuration | ||
| 366 | pub ranging: u8, | ||
| 367 | /// 2011 - the preamble symbol repititions | ||
| 368 | pub uwb_preamble_symbol_repetitions: u8, | ||
| 369 | /// 2011 - indicates the data rate | ||
| 370 | pub datrate: u8, | ||
| 371 | } | ||
| 372 | |||
| 373 | impl Default for DataRequest { | ||
| 374 | fn default() -> Self { | ||
| 375 | Self { | ||
| 376 | msdu_ptr: 0 as *const u8, | ||
| 377 | src_addr_mode: AddressMode::NoAddress, | ||
| 378 | dst_addr_mode: AddressMode::NoAddress, | ||
| 379 | dst_pan_id: PanId([0, 0]), | ||
| 380 | dst_address: MacAddress { short: [0, 0] }, | ||
| 381 | msdu_length: 0, | ||
| 382 | msdu_handle: 0, | ||
| 383 | ack_tx: 0, | ||
| 384 | gts_tx: false, | ||
| 385 | indirect_tx: 0, | ||
| 386 | security_level: SecurityLevel::Unsecure, | ||
| 387 | key_id_mode: KeyIdMode::Implicite, | ||
| 388 | key_index: 0, | ||
| 389 | key_source: [0u8; 8], | ||
| 390 | uwbprf: 0, | ||
| 391 | ranging: 0, | ||
| 392 | uwb_preamble_symbol_repetitions: 0, | ||
| 393 | datrate: 0, | ||
| 394 | } | ||
| 395 | } | ||
| 396 | } | ||
| 397 | |||
| 398 | impl MacCommand for DataRequest { | ||
| 399 | const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::McpsDataReq; | ||
| 400 | const SIZE: usize = 40; | ||
| 401 | } | ||
| 402 | |||
| 403 | /// for MCPS PURGE Request used to purge an MSDU from the transaction queue | ||
| 404 | #[repr(C)] | ||
| 405 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 406 | pub struct PurgeRequest { | ||
| 407 | /// the handle associated with the MSDU to be purged from the transaction | ||
| 408 | /// queue | ||
| 409 | pub msdu_handle: u8, | ||
| 410 | } | ||
| 411 | |||
| 412 | impl MacCommand for PurgeRequest { | ||
| 413 | const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::McpsPurgeReq; | ||
| 414 | const SIZE: usize = 4; | ||
| 415 | } | ||
| 416 | |||
| 417 | /// MLME ASSOCIATE Response used to initiate a response to an MLME-ASSOCIATE.indication | ||
| 418 | #[repr(C)] | ||
| 419 | #[derive(Default)] | ||
| 420 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 421 | pub struct AssociateResponse { | ||
| 422 | /// extended address of the device requesting association | ||
| 423 | pub device_address: [u8; 8], | ||
| 424 | /// 16-bitshort device address allocated by the coordinator on successful | ||
| 425 | /// association | ||
| 426 | pub assoc_short_address: [u8; 2], | ||
| 427 | /// status of the association attempt | ||
| 428 | pub status: MacStatus, | ||
| 429 | /// security level to be used | ||
| 430 | pub security_level: SecurityLevel, | ||
| 431 | /// the originator of the key to be used | ||
| 432 | pub key_source: [u8; 8], | ||
| 433 | /// the mode used to identify the key to be used | ||
| 434 | pub key_id_mode: KeyIdMode, | ||
| 435 | /// the index of the key to be used | ||
| 436 | pub key_index: u8, | ||
| 437 | } | ||
| 438 | |||
| 439 | impl MacCommand for AssociateResponse { | ||
| 440 | const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeAssociateRes; | ||
| 441 | const SIZE: usize = 24; | ||
| 442 | } | ||
| 443 | |||
| 444 | /// MLME ORPHAN Response used to respond to the MLME ORPHAN Indication | ||
| 445 | #[repr(C)] | ||
| 446 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 447 | pub struct OrphanResponse { | ||
| 448 | /// extended address of the orphaned device | ||
| 449 | pub orphan_address: [u8; 8], | ||
| 450 | /// short address allocated to the orphaned device | ||
| 451 | pub short_address: [u8; 2], | ||
| 452 | /// if the orphaned device is associated with coordinator or not | ||
| 453 | pub associated_member: bool, | ||
| 454 | /// security level to be used | ||
| 455 | pub security_level: SecurityLevel, | ||
| 456 | /// the originator of the key to be used | ||
| 457 | pub key_source: [u8; 8], | ||
| 458 | /// the mode used to identify the key to be used | ||
| 459 | pub key_id_mode: KeyIdMode, | ||
| 460 | /// the index of the key to be used | ||
| 461 | pub key_index: u8, | ||
| 462 | } | ||
| 463 | |||
| 464 | impl MacCommand for OrphanResponse { | ||
| 465 | const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeOrphanRes; | ||
| 466 | const SIZE: usize = 24; | ||
| 467 | } | ||
diff --git a/embassy-stm32-wpan/src/mac/consts.rs b/embassy-stm32-wpan/src/mac/consts.rs new file mode 100644 index 000000000..56903d980 --- /dev/null +++ b/embassy-stm32-wpan/src/mac/consts.rs | |||
| @@ -0,0 +1,4 @@ | |||
| 1 | pub const MAX_PAN_DESC_SUPPORTED: usize = 6; | ||
| 2 | pub const MAX_SOUNDING_LIST_SUPPORTED: usize = 6; | ||
| 3 | pub const MAX_PENDING_ADDRESS: usize = 7; | ||
| 4 | pub const MAX_ED_SCAN_RESULTS_SUPPORTED: usize = 16; | ||
diff --git a/embassy-stm32-wpan/src/mac/event.rs b/embassy-stm32-wpan/src/mac/event.rs new file mode 100644 index 000000000..dfce21fea --- /dev/null +++ b/embassy-stm32-wpan/src/mac/event.rs | |||
| @@ -0,0 +1,94 @@ | |||
| 1 | use super::helpers::to_u16; | ||
| 2 | use super::indications::{ | ||
| 3 | AssociateIndication, BeaconNotifyIndication, CommStatusIndication, DataIndication, DisassociateIndication, | ||
| 4 | DpsIndication, GtsIndication, OrphanIndication, PollIndication, SyncLossIndication, | ||
| 5 | }; | ||
| 6 | use super::responses::{ | ||
| 7 | AssociateConfirm, CalibrateConfirm, DataConfirm, DisassociateConfirm, DpsConfirm, GetConfirm, GtsConfirm, | ||
| 8 | PollConfirm, PurgeConfirm, ResetConfirm, RxEnableConfirm, ScanConfirm, SetConfirm, SoundingConfirm, StartConfirm, | ||
| 9 | }; | ||
| 10 | use crate::mac::opcodes::OpcodeM0ToM4; | ||
| 11 | |||
| 12 | pub trait ParseableMacEvent { | ||
| 13 | const SIZE: usize; | ||
| 14 | |||
| 15 | fn validate(buf: &[u8]) -> Result<(), ()> { | ||
| 16 | if buf.len() < Self::SIZE { | ||
| 17 | return Err(()); | ||
| 18 | } | ||
| 19 | |||
| 20 | Ok(()) | ||
| 21 | } | ||
| 22 | |||
| 23 | fn try_parse(buf: &[u8]) -> Result<Self, ()> | ||
| 24 | where | ||
| 25 | Self: Sized; | ||
| 26 | } | ||
| 27 | |||
| 28 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 29 | pub enum MacEvent { | ||
| 30 | MlmeAssociateCnf(AssociateConfirm), | ||
| 31 | MlmeDisassociateCnf(DisassociateConfirm), | ||
| 32 | MlmeGetCnf(GetConfirm), | ||
| 33 | MlmeGtsCnf(GtsConfirm), | ||
| 34 | MlmeResetCnf(ResetConfirm), | ||
| 35 | MlmeRxEnableCnf(RxEnableConfirm), | ||
| 36 | MlmeScanCnf(ScanConfirm), | ||
| 37 | MlmeSetCnf(SetConfirm), | ||
| 38 | MlmeStartCnf(StartConfirm), | ||
| 39 | MlmePollCnf(PollConfirm), | ||
| 40 | MlmeDpsCnf(DpsConfirm), | ||
| 41 | MlmeSoundingCnf(SoundingConfirm), | ||
| 42 | MlmeCalibrateCnf(CalibrateConfirm), | ||
| 43 | McpsDataCnf(DataConfirm), | ||
| 44 | McpsPurgeCnf(PurgeConfirm), | ||
| 45 | MlmeAssociateInd(AssociateIndication), | ||
| 46 | MlmeDisassociateInd(DisassociateIndication), | ||
| 47 | MlmeBeaconNotifyInd(BeaconNotifyIndication), | ||
| 48 | MlmeCommStatusInd(CommStatusIndication), | ||
| 49 | MlmeGtsInd(GtsIndication), | ||
| 50 | MlmeOrphanInd(OrphanIndication), | ||
| 51 | MlmeSyncLossInd(SyncLossIndication), | ||
| 52 | MlmeDpsInd(DpsIndication), | ||
| 53 | McpsDataInd(DataIndication), | ||
| 54 | MlmePollInd(PollIndication), | ||
| 55 | } | ||
| 56 | |||
| 57 | impl TryFrom<&[u8]> for MacEvent { | ||
| 58 | type Error = (); | ||
| 59 | |||
| 60 | fn try_from(value: &[u8]) -> Result<Self, Self::Error> { | ||
| 61 | let opcode = to_u16(&value[0..2]); | ||
| 62 | let opcode = OpcodeM0ToM4::try_from(opcode)?; | ||
| 63 | |||
| 64 | let buf = &value[2..]; | ||
| 65 | |||
| 66 | match opcode { | ||
| 67 | OpcodeM0ToM4::MlmeAssociateCnf => Ok(Self::MlmeAssociateCnf(AssociateConfirm::try_parse(buf)?)), | ||
| 68 | OpcodeM0ToM4::MlmeDisassociateCnf => Ok(Self::MlmeDisassociateCnf(DisassociateConfirm::try_parse(buf)?)), | ||
| 69 | OpcodeM0ToM4::MlmeGetCnf => Ok(Self::MlmeGetCnf(GetConfirm::try_parse(buf)?)), | ||
| 70 | OpcodeM0ToM4::MlmeGtsCnf => Ok(Self::MlmeGtsCnf(GtsConfirm::try_parse(buf)?)), | ||
| 71 | OpcodeM0ToM4::MlmeResetCnf => Ok(Self::MlmeResetCnf(ResetConfirm::try_parse(buf)?)), | ||
| 72 | OpcodeM0ToM4::MlmeRxEnableCnf => Ok(Self::MlmeRxEnableCnf(RxEnableConfirm::try_parse(buf)?)), | ||
| 73 | OpcodeM0ToM4::MlmeScanCnf => Ok(Self::MlmeScanCnf(ScanConfirm::try_parse(buf)?)), | ||
| 74 | OpcodeM0ToM4::MlmeSetCnf => Ok(Self::MlmeSetCnf(SetConfirm::try_parse(buf)?)), | ||
| 75 | OpcodeM0ToM4::MlmeStartCnf => Ok(Self::MlmeStartCnf(StartConfirm::try_parse(buf)?)), | ||
| 76 | OpcodeM0ToM4::MlmePollCnf => Ok(Self::MlmePollCnf(PollConfirm::try_parse(buf)?)), | ||
| 77 | OpcodeM0ToM4::MlmeDpsCnf => Ok(Self::MlmeDpsCnf(DpsConfirm::try_parse(buf)?)), | ||
| 78 | OpcodeM0ToM4::MlmeSoundingCnf => Ok(Self::MlmeSoundingCnf(SoundingConfirm::try_parse(buf)?)), | ||
| 79 | OpcodeM0ToM4::MlmeCalibrateCnf => Ok(Self::MlmeCalibrateCnf(CalibrateConfirm::try_parse(buf)?)), | ||
| 80 | OpcodeM0ToM4::McpsDataCnf => Ok(Self::McpsDataCnf(DataConfirm::try_parse(buf)?)), | ||
| 81 | OpcodeM0ToM4::McpsPurgeCnf => Ok(Self::McpsPurgeCnf(PurgeConfirm::try_parse(buf)?)), | ||
| 82 | OpcodeM0ToM4::MlmeAssociateInd => Ok(Self::MlmeAssociateInd(AssociateIndication::try_parse(buf)?)), | ||
| 83 | OpcodeM0ToM4::MlmeDisassociateInd => Ok(Self::MlmeDisassociateInd(DisassociateIndication::try_parse(buf)?)), | ||
| 84 | OpcodeM0ToM4::MlmeBeaconNotifyInd => Ok(Self::MlmeBeaconNotifyInd(BeaconNotifyIndication::try_parse(buf)?)), | ||
| 85 | OpcodeM0ToM4::MlmeCommStatusInd => Ok(Self::MlmeCommStatusInd(CommStatusIndication::try_parse(buf)?)), | ||
| 86 | OpcodeM0ToM4::MlmeGtsInd => Ok(Self::MlmeGtsInd(GtsIndication::try_parse(buf)?)), | ||
| 87 | OpcodeM0ToM4::MlmeOrphanInd => Ok(Self::MlmeOrphanInd(OrphanIndication::try_parse(buf)?)), | ||
| 88 | OpcodeM0ToM4::MlmeSyncLossInd => Ok(Self::MlmeSyncLossInd(SyncLossIndication::try_parse(buf)?)), | ||
| 89 | OpcodeM0ToM4::MlmeDpsInd => Ok(Self::MlmeDpsInd(DpsIndication::try_parse(buf)?)), | ||
| 90 | OpcodeM0ToM4::McpsDataInd => Ok(Self::McpsDataInd(DataIndication::try_parse(buf)?)), | ||
| 91 | OpcodeM0ToM4::MlmePollInd => Ok(Self::MlmePollInd(PollIndication::try_parse(buf)?)), | ||
| 92 | } | ||
| 93 | } | ||
| 94 | } | ||
diff --git a/embassy-stm32-wpan/src/mac/helpers.rs b/embassy-stm32-wpan/src/mac/helpers.rs new file mode 100644 index 000000000..5a5bf8a85 --- /dev/null +++ b/embassy-stm32-wpan/src/mac/helpers.rs | |||
| @@ -0,0 +1,7 @@ | |||
| 1 | pub fn to_u16(buf: &[u8]) -> u16 { | ||
| 2 | ((buf[1] as u16) << 8) | buf[0] as u16 | ||
| 3 | } | ||
| 4 | |||
| 5 | pub fn to_u32(buf: &[u8]) -> u32 { | ||
| 6 | ((buf[0] as u32) << 0) + ((buf[1] as u32) << 8) + ((buf[2] as u32) << 16) + ((buf[3] as u32) << 24) | ||
| 7 | } | ||
diff --git a/embassy-stm32-wpan/src/mac/indications.rs b/embassy-stm32-wpan/src/mac/indications.rs new file mode 100644 index 000000000..6df4aa23a --- /dev/null +++ b/embassy-stm32-wpan/src/mac/indications.rs | |||
| @@ -0,0 +1,470 @@ | |||
| 1 | use super::consts::MAX_PENDING_ADDRESS; | ||
| 2 | use super::event::ParseableMacEvent; | ||
| 3 | use super::helpers::to_u32; | ||
| 4 | use super::typedefs::{ | ||
| 5 | AddressMode, Capabilities, DisassociationReason, KeyIdMode, MacAddress, MacChannel, MacStatus, PanDescriptor, | ||
| 6 | PanId, SecurityLevel, | ||
| 7 | }; | ||
| 8 | |||
| 9 | /// MLME ASSOCIATE Indication which will be used by the MAC | ||
| 10 | /// to indicate the reception of an association request command | ||
| 11 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 12 | pub struct AssociateIndication { | ||
| 13 | /// Extended address of the device requesting association | ||
| 14 | pub device_address: [u8; 8], | ||
| 15 | /// Operational capabilities of the device requesting association | ||
| 16 | pub capability_information: Capabilities, | ||
| 17 | /// Security level purportedly used by the received MAC command frame | ||
| 18 | pub security_level: SecurityLevel, | ||
| 19 | /// The mode used to identify the key used by the originator of frame | ||
| 20 | pub key_id_mode: KeyIdMode, | ||
| 21 | /// Index of the key used by the originator of the received frame | ||
| 22 | pub key_index: u8, | ||
| 23 | /// The originator of the key used by the originator of the received frame | ||
| 24 | pub key_source: [u8; 8], | ||
| 25 | } | ||
| 26 | |||
| 27 | impl ParseableMacEvent for AssociateIndication { | ||
| 28 | const SIZE: usize = 20; | ||
| 29 | |||
| 30 | fn try_parse(buf: &[u8]) -> Result<Self, ()> { | ||
| 31 | Self::validate(buf)?; | ||
| 32 | |||
| 33 | Ok(Self { | ||
| 34 | device_address: [buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]], | ||
| 35 | capability_information: Capabilities::from_bits(buf[8]).ok_or(())?, | ||
| 36 | security_level: SecurityLevel::try_from(buf[9])?, | ||
| 37 | key_id_mode: KeyIdMode::try_from(buf[10])?, | ||
| 38 | key_index: buf[11], | ||
| 39 | key_source: [buf[12], buf[13], buf[14], buf[15], buf[16], buf[17], buf[18], buf[19]], | ||
| 40 | }) | ||
| 41 | } | ||
| 42 | } | ||
| 43 | |||
| 44 | /// MLME DISASSOCIATE indication which will be used to send | ||
| 45 | /// disassociation indication to the application. | ||
| 46 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 47 | pub struct DisassociateIndication { | ||
| 48 | /// Extended address of the device requesting association | ||
| 49 | pub device_address: [u8; 8], | ||
| 50 | /// The reason for the disassociation | ||
| 51 | pub disassociation_reason: DisassociationReason, | ||
| 52 | /// The security level to be used | ||
| 53 | pub security_level: SecurityLevel, | ||
| 54 | /// The mode used to identify the key to be used | ||
| 55 | pub key_id_mode: KeyIdMode, | ||
| 56 | /// The index of the key to be used | ||
| 57 | pub key_index: u8, | ||
| 58 | /// The originator of the key to be used | ||
| 59 | pub key_source: [u8; 8], | ||
| 60 | } | ||
| 61 | |||
| 62 | impl ParseableMacEvent for DisassociateIndication { | ||
| 63 | const SIZE: usize = 20; | ||
| 64 | |||
| 65 | fn try_parse(buf: &[u8]) -> Result<Self, ()> { | ||
| 66 | Self::validate(buf)?; | ||
| 67 | |||
| 68 | Ok(Self { | ||
| 69 | device_address: [buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]], | ||
| 70 | disassociation_reason: DisassociationReason::try_from(buf[8])?, | ||
| 71 | security_level: SecurityLevel::try_from(buf[9])?, | ||
| 72 | key_id_mode: KeyIdMode::try_from(buf[10])?, | ||
| 73 | key_index: buf[11], | ||
| 74 | key_source: [buf[12], buf[13], buf[14], buf[15], buf[16], buf[17], buf[18], buf[19]], | ||
| 75 | }) | ||
| 76 | } | ||
| 77 | } | ||
| 78 | |||
| 79 | /// MLME BEACON NOTIIFY Indication which is used to send parameters contained | ||
| 80 | /// within a beacon frame received by the MAC to the application | ||
| 81 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 82 | pub struct BeaconNotifyIndication { | ||
| 83 | /// he set of octets comprising the beacon payload to be transferred | ||
| 84 | /// from the MAC sublayer entity to the next higher layer | ||
| 85 | pub sdu_ptr: *const u8, | ||
| 86 | /// The PAN Descriptor for the received beacon | ||
| 87 | pub pan_descriptor: PanDescriptor, | ||
| 88 | /// The list of addresses of the devices | ||
| 89 | pub addr_list: [MacAddress; MAX_PENDING_ADDRESS], | ||
| 90 | /// Beacon Sequence Number | ||
| 91 | pub bsn: u8, | ||
| 92 | /// The beacon pending address specification | ||
| 93 | pub pend_addr_spec: u8, | ||
| 94 | /// Number of octets contained in the beacon payload of the beacon frame | ||
| 95 | pub sdu_length: u8, | ||
| 96 | } | ||
| 97 | |||
| 98 | impl ParseableMacEvent for BeaconNotifyIndication { | ||
| 99 | const SIZE: usize = 88; | ||
| 100 | |||
| 101 | fn try_parse(buf: &[u8]) -> Result<Self, ()> { | ||
| 102 | // TODO: this is unchecked | ||
| 103 | |||
| 104 | Self::validate(buf)?; | ||
| 105 | |||
| 106 | let addr_list = [ | ||
| 107 | MacAddress::try_from(&buf[26..34])?, | ||
| 108 | MacAddress::try_from(&buf[34..42])?, | ||
| 109 | MacAddress::try_from(&buf[42..50])?, | ||
| 110 | MacAddress::try_from(&buf[50..58])?, | ||
| 111 | MacAddress::try_from(&buf[58..66])?, | ||
| 112 | MacAddress::try_from(&buf[66..74])?, | ||
| 113 | MacAddress::try_from(&buf[74..82])?, | ||
| 114 | ]; | ||
| 115 | |||
| 116 | Ok(Self { | ||
| 117 | sdu_ptr: to_u32(&buf[0..4]) as *const u8, | ||
| 118 | pan_descriptor: PanDescriptor::try_from(&buf[4..26])?, | ||
| 119 | addr_list, | ||
| 120 | bsn: buf[82], | ||
| 121 | pend_addr_spec: buf[83], | ||
| 122 | sdu_length: buf[83], | ||
| 123 | }) | ||
| 124 | } | ||
| 125 | } | ||
| 126 | |||
| 127 | /// MLME COMM STATUS Indication which is used by the MAC to indicate a communications status | ||
| 128 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 129 | pub struct CommStatusIndication { | ||
| 130 | /// The 16-bit PAN identifier of the device from which the frame | ||
| 131 | /// was received or to which the frame was being sent | ||
| 132 | pub pan_id: PanId, | ||
| 133 | /// Source addressing mode | ||
| 134 | pub src_addr_mode: AddressMode, | ||
| 135 | /// Destination addressing mode | ||
| 136 | pub dst_addr_mode: AddressMode, | ||
| 137 | /// Source address | ||
| 138 | pub src_address: MacAddress, | ||
| 139 | /// Destination address | ||
| 140 | pub dst_address: MacAddress, | ||
| 141 | /// The communications status | ||
| 142 | pub status: MacStatus, | ||
| 143 | /// Security level to be used | ||
| 144 | pub security_level: SecurityLevel, | ||
| 145 | /// Mode used to identify the key to be used | ||
| 146 | pub key_id_mode: KeyIdMode, | ||
| 147 | /// Index of the key to be used | ||
| 148 | pub key_index: u8, | ||
| 149 | /// Originator of the key to be used | ||
| 150 | pub key_source: [u8; 8], | ||
| 151 | } | ||
| 152 | |||
| 153 | impl ParseableMacEvent for CommStatusIndication { | ||
| 154 | const SIZE: usize = 32; | ||
| 155 | |||
| 156 | fn try_parse(buf: &[u8]) -> Result<Self, ()> { | ||
| 157 | Self::validate(buf)?; | ||
| 158 | |||
| 159 | let src_addr_mode = AddressMode::try_from(buf[2])?; | ||
| 160 | let dst_addr_mode = AddressMode::try_from(buf[3])?; | ||
| 161 | |||
| 162 | let src_address = match src_addr_mode { | ||
| 163 | AddressMode::NoAddress => MacAddress { short: [0, 0] }, | ||
| 164 | AddressMode::Reserved => MacAddress { short: [0, 0] }, | ||
| 165 | AddressMode::Short => MacAddress { | ||
| 166 | short: [buf[4], buf[5]], | ||
| 167 | }, | ||
| 168 | AddressMode::Extended => MacAddress { | ||
| 169 | extended: [buf[4], buf[5], buf[6], buf[7], buf[8], buf[9], buf[10], buf[11]], | ||
| 170 | }, | ||
| 171 | }; | ||
| 172 | |||
| 173 | let dst_address = match dst_addr_mode { | ||
| 174 | AddressMode::NoAddress => MacAddress { short: [0, 0] }, | ||
| 175 | AddressMode::Reserved => MacAddress { short: [0, 0] }, | ||
| 176 | AddressMode::Short => MacAddress { | ||
| 177 | short: [buf[12], buf[13]], | ||
| 178 | }, | ||
| 179 | AddressMode::Extended => MacAddress { | ||
| 180 | extended: [buf[12], buf[13], buf[14], buf[15], buf[16], buf[17], buf[18], buf[19]], | ||
| 181 | }, | ||
| 182 | }; | ||
| 183 | |||
| 184 | Ok(Self { | ||
| 185 | pan_id: PanId([buf[0], buf[1]]), | ||
| 186 | src_addr_mode, | ||
| 187 | dst_addr_mode, | ||
| 188 | src_address, | ||
| 189 | dst_address, | ||
| 190 | status: MacStatus::try_from(buf[20])?, | ||
| 191 | security_level: SecurityLevel::try_from(buf[21])?, | ||
| 192 | key_id_mode: KeyIdMode::try_from(buf[22])?, | ||
| 193 | key_index: buf[23], | ||
| 194 | key_source: [buf[24], buf[25], buf[26], buf[27], buf[28], buf[29], buf[30], buf[31]], | ||
| 195 | }) | ||
| 196 | } | ||
| 197 | } | ||
| 198 | |||
| 199 | /// MLME GTS Indication indicates that a GTS has been allocated or that a | ||
| 200 | /// previously allocated GTS has been deallocated | ||
| 201 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 202 | pub struct GtsIndication { | ||
| 203 | /// The short address of the device that has been allocated or deallocated a GTS | ||
| 204 | pub device_address: [u8; 2], | ||
| 205 | /// The characteristics of the GTS | ||
| 206 | pub gts_characteristics: u8, | ||
| 207 | /// Security level to be used | ||
| 208 | pub security_level: SecurityLevel, | ||
| 209 | /// Mode used to identify the key to be used | ||
| 210 | pub key_id_mode: KeyIdMode, | ||
| 211 | /// Index of the key to be used | ||
| 212 | pub key_index: u8, | ||
| 213 | /// Originator of the key to be used | ||
| 214 | pub key_source: [u8; 8], | ||
| 215 | } | ||
| 216 | |||
| 217 | impl ParseableMacEvent for GtsIndication { | ||
| 218 | const SIZE: usize = 16; | ||
| 219 | |||
| 220 | fn try_parse(buf: &[u8]) -> Result<Self, ()> { | ||
| 221 | Self::validate(buf)?; | ||
| 222 | |||
| 223 | Ok(Self { | ||
| 224 | device_address: [buf[0], buf[1]], | ||
| 225 | gts_characteristics: buf[2], | ||
| 226 | security_level: SecurityLevel::try_from(buf[3])?, | ||
| 227 | key_id_mode: KeyIdMode::try_from(buf[4])?, | ||
| 228 | key_index: buf[5], | ||
| 229 | // 2 byte stuffing | ||
| 230 | key_source: [buf[8], buf[9], buf[10], buf[11], buf[12], buf[13], buf[14], buf[15]], | ||
| 231 | }) | ||
| 232 | } | ||
| 233 | } | ||
| 234 | |||
| 235 | /// MLME ORPHAN Indication which is used by the coordinator to notify the | ||
| 236 | /// application of the presence of an orphaned device | ||
| 237 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 238 | pub struct OrphanIndication { | ||
| 239 | /// Extended address of the orphaned device | ||
| 240 | pub orphan_address: [u8; 8], | ||
| 241 | /// Originator of the key used by the originator of the received frame | ||
| 242 | pub key_source: [u8; 8], | ||
| 243 | /// Security level purportedly used by the received MAC command frame | ||
| 244 | pub security_level: SecurityLevel, | ||
| 245 | /// Mode used to identify the key used by originator of received frame | ||
| 246 | pub key_id_mode: KeyIdMode, | ||
| 247 | /// Index of the key used by the originator of the received frame | ||
| 248 | pub key_index: u8, | ||
| 249 | } | ||
| 250 | |||
| 251 | impl ParseableMacEvent for OrphanIndication { | ||
| 252 | const SIZE: usize = 20; | ||
| 253 | |||
| 254 | fn try_parse(buf: &[u8]) -> Result<Self, ()> { | ||
| 255 | Self::validate(buf)?; | ||
| 256 | |||
| 257 | Ok(Self { | ||
| 258 | orphan_address: [buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]], | ||
| 259 | key_source: [buf[8], buf[9], buf[10], buf[11], buf[12], buf[13], buf[14], buf[15]], | ||
| 260 | security_level: SecurityLevel::try_from(buf[16])?, | ||
| 261 | key_id_mode: KeyIdMode::try_from(buf[17])?, | ||
| 262 | key_index: buf[18], | ||
| 263 | // 1 byte stuffing | ||
| 264 | }) | ||
| 265 | } | ||
| 266 | } | ||
| 267 | |||
| 268 | /// MLME SYNC LOSS Indication which is used by the MAC to indicate the loss | ||
| 269 | /// of synchronization with the coordinator | ||
| 270 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 271 | pub struct SyncLossIndication { | ||
| 272 | /// The PAN identifier with which the device lost synchronization or to which it was realigned | ||
| 273 | pub pan_id: PanId, | ||
| 274 | /// The reason that synchronization was lost | ||
| 275 | pub loss_reason: u8, | ||
| 276 | /// The logical channel on which the device lost synchronization or to whi | ||
| 277 | pub channel_number: MacChannel, | ||
| 278 | /// The channel page on which the device lost synchronization or to which | ||
| 279 | pub channel_page: u8, | ||
| 280 | /// The security level used by the received MAC frame | ||
| 281 | pub security_level: SecurityLevel, | ||
| 282 | /// Mode used to identify the key used by originator of received frame | ||
| 283 | pub key_id_mode: KeyIdMode, | ||
| 284 | /// Index of the key used by the originator of the received frame | ||
| 285 | pub key_index: u8, | ||
| 286 | /// Originator of the key used by the originator of the received frame | ||
| 287 | pub key_source: [u8; 8], | ||
| 288 | } | ||
| 289 | |||
| 290 | impl ParseableMacEvent for SyncLossIndication { | ||
| 291 | const SIZE: usize = 16; | ||
| 292 | |||
| 293 | fn try_parse(buf: &[u8]) -> Result<Self, ()> { | ||
| 294 | Self::validate(buf)?; | ||
| 295 | |||
| 296 | Ok(Self { | ||
| 297 | pan_id: PanId([buf[0], buf[1]]), | ||
| 298 | loss_reason: buf[2], | ||
| 299 | channel_number: MacChannel::try_from(buf[3])?, | ||
| 300 | channel_page: buf[4], | ||
| 301 | security_level: SecurityLevel::try_from(buf[5])?, | ||
| 302 | key_id_mode: KeyIdMode::try_from(buf[6])?, | ||
| 303 | key_index: buf[7], | ||
| 304 | key_source: [buf[8], buf[9], buf[10], buf[11], buf[12], buf[13], buf[14], buf[15]], | ||
| 305 | }) | ||
| 306 | } | ||
| 307 | } | ||
| 308 | |||
| 309 | /// MLME DPS Indication which indicates the expiration of the DPSIndexDuration | ||
| 310 | /// and the resetting of the DPS values in the PHY | ||
| 311 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 312 | pub struct DpsIndication; | ||
| 313 | |||
| 314 | impl ParseableMacEvent for DpsIndication { | ||
| 315 | const SIZE: usize = 4; | ||
| 316 | |||
| 317 | fn try_parse(buf: &[u8]) -> Result<Self, ()> { | ||
| 318 | Self::validate(buf)?; | ||
| 319 | |||
| 320 | Ok(Self) | ||
| 321 | } | ||
| 322 | } | ||
| 323 | |||
| 324 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 325 | #[repr(C, align(8))] | ||
| 326 | pub struct DataIndication { | ||
| 327 | /// Pointer to the set of octets forming the MSDU being indicated | ||
| 328 | pub msdu_ptr: *const u8, | ||
| 329 | /// Source addressing mode used | ||
| 330 | pub src_addr_mode: AddressMode, | ||
| 331 | /// Source PAN ID | ||
| 332 | pub src_pan_id: PanId, | ||
| 333 | /// Source address | ||
| 334 | pub src_address: MacAddress, | ||
| 335 | /// Destination addressing mode used | ||
| 336 | pub dst_addr_mode: AddressMode, | ||
| 337 | /// Destination PAN ID | ||
| 338 | pub dst_pan_id: PanId, | ||
| 339 | /// Destination address | ||
| 340 | pub dst_address: MacAddress, | ||
| 341 | /// The number of octets contained in the MSDU being indicated | ||
| 342 | pub msdu_length: u8, | ||
| 343 | /// QI value measured during reception of the MPDU | ||
| 344 | pub mpdu_link_quality: u8, | ||
| 345 | /// The data sequence number of the received data frame | ||
| 346 | pub dsn: u8, | ||
| 347 | /// The time, in symbols, at which the data were received | ||
| 348 | pub time_stamp: [u8; 4], | ||
| 349 | /// The security level purportedly used by the received data frame | ||
| 350 | pub security_level: SecurityLevel, | ||
| 351 | /// Mode used to identify the key used by originator of received frame | ||
| 352 | pub key_id_mode: KeyIdMode, | ||
| 353 | /// The originator of the key | ||
| 354 | pub key_source: [u8; 8], | ||
| 355 | /// The index of the key | ||
| 356 | pub key_index: u8, | ||
| 357 | /// he pulse repetition value of the received PPDU | ||
| 358 | pub uwbprf: u8, | ||
| 359 | /// The preamble symbol repetitions of the UWB PHY frame | ||
| 360 | pub uwn_preamble_symbol_repetitions: u8, | ||
| 361 | /// Indicates the data rate | ||
| 362 | pub datrate: u8, | ||
| 363 | /// time units corresponding to an RMARKER at the antenna at the end of a ranging exchange, | ||
| 364 | pub ranging_received: u8, | ||
| 365 | pub ranging_counter_start: u32, | ||
| 366 | pub ranging_counter_stop: u32, | ||
| 367 | /// ime units in a message exchange over which the tracking offset was measured | ||
| 368 | pub ranging_tracking_interval: u32, | ||
| 369 | /// time units slipped or advanced by the radio tracking system | ||
| 370 | pub ranging_offset: u32, | ||
| 371 | /// The FoM characterizing the ranging measurement | ||
| 372 | pub ranging_fom: u8, | ||
| 373 | /// The Received Signal Strength Indicator measured | ||
| 374 | pub rssi: u8, | ||
| 375 | } | ||
| 376 | |||
| 377 | impl ParseableMacEvent for DataIndication { | ||
| 378 | const SIZE: usize = 68; | ||
| 379 | |||
| 380 | fn try_parse(buf: &[u8]) -> Result<Self, ()> { | ||
| 381 | Self::validate(buf)?; | ||
| 382 | |||
| 383 | let src_addr_mode = AddressMode::try_from(buf[4])?; | ||
| 384 | let src_address = match src_addr_mode { | ||
| 385 | AddressMode::NoAddress => MacAddress { short: [0, 0] }, | ||
| 386 | AddressMode::Reserved => MacAddress { short: [0, 0] }, | ||
| 387 | AddressMode::Short => MacAddress { | ||
| 388 | short: [buf[7], buf[8]], | ||
| 389 | }, | ||
| 390 | AddressMode::Extended => MacAddress { | ||
| 391 | extended: [buf[7], buf[8], buf[9], buf[10], buf[11], buf[12], buf[13], buf[14]], | ||
| 392 | }, | ||
| 393 | }; | ||
| 394 | |||
| 395 | let dst_addr_mode = AddressMode::try_from(buf[15])?; | ||
| 396 | let dst_address = match dst_addr_mode { | ||
| 397 | AddressMode::NoAddress => MacAddress { short: [0, 0] }, | ||
| 398 | AddressMode::Reserved => MacAddress { short: [0, 0] }, | ||
| 399 | AddressMode::Short => MacAddress { | ||
| 400 | short: [buf[18], buf[19]], | ||
| 401 | }, | ||
| 402 | AddressMode::Extended => MacAddress { | ||
| 403 | extended: [buf[18], buf[19], buf[20], buf[21], buf[22], buf[23], buf[24], buf[25]], | ||
| 404 | }, | ||
| 405 | }; | ||
| 406 | |||
| 407 | Ok(Self { | ||
| 408 | msdu_ptr: to_u32(&buf[0..4]) as *const u8, | ||
| 409 | src_addr_mode, | ||
| 410 | src_pan_id: PanId([buf[5], buf[6]]), | ||
| 411 | src_address, | ||
| 412 | dst_addr_mode, | ||
| 413 | dst_pan_id: PanId([buf[16], buf[17]]), | ||
| 414 | dst_address, | ||
| 415 | msdu_length: buf[26], | ||
| 416 | mpdu_link_quality: buf[27], | ||
| 417 | dsn: buf[28], | ||
| 418 | time_stamp: [buf[29], buf[30], buf[31], buf[32]], | ||
| 419 | security_level: SecurityLevel::try_from(buf[33]).unwrap_or(SecurityLevel::Unsecure), // TODO: this is totaly wrong, but I'm too smol brain to fix it | ||
| 420 | key_id_mode: KeyIdMode::try_from(buf[34]).unwrap_or(KeyIdMode::Implicite), // TODO: this is totaly wrong, but I'm too smol brain to fix it | ||
| 421 | key_source: [buf[35], buf[36], buf[37], buf[38], buf[39], buf[40], buf[41], buf[42]], | ||
| 422 | key_index: buf[43], | ||
| 423 | uwbprf: buf[44], | ||
| 424 | uwn_preamble_symbol_repetitions: buf[45], | ||
| 425 | datrate: buf[46], | ||
| 426 | ranging_received: buf[47], | ||
| 427 | ranging_counter_start: to_u32(&buf[48..52]), | ||
| 428 | ranging_counter_stop: to_u32(&buf[52..56]), | ||
| 429 | ranging_tracking_interval: to_u32(&buf[56..60]), | ||
| 430 | ranging_offset: to_u32(&buf[60..64]), | ||
| 431 | ranging_fom: buf[65], | ||
| 432 | rssi: buf[66], | ||
| 433 | }) | ||
| 434 | } | ||
| 435 | } | ||
| 436 | |||
| 437 | /// MLME POLL Indication which will be used for indicating the Data Request | ||
| 438 | /// reception to upper layer as defined in Zigbee r22 - D.8.2 | ||
| 439 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 440 | pub struct PollIndication { | ||
| 441 | /// addressing mode used | ||
| 442 | pub addr_mode: AddressMode, | ||
| 443 | /// Poll requester address | ||
| 444 | pub request_address: MacAddress, | ||
| 445 | } | ||
| 446 | |||
| 447 | impl ParseableMacEvent for PollIndication { | ||
| 448 | const SIZE: usize = 9; | ||
| 449 | |||
| 450 | fn try_parse(buf: &[u8]) -> Result<Self, ()> { | ||
| 451 | Self::validate(buf)?; | ||
| 452 | |||
| 453 | let addr_mode = AddressMode::try_from(buf[0])?; | ||
| 454 | let request_address = match addr_mode { | ||
| 455 | AddressMode::NoAddress => MacAddress { short: [0, 0] }, | ||
| 456 | AddressMode::Reserved => MacAddress { short: [0, 0] }, | ||
| 457 | AddressMode::Short => MacAddress { | ||
| 458 | short: [buf[1], buf[2]], | ||
| 459 | }, | ||
| 460 | AddressMode::Extended => MacAddress { | ||
| 461 | extended: [buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7], buf[8]], | ||
| 462 | }, | ||
| 463 | }; | ||
| 464 | |||
| 465 | Ok(Self { | ||
| 466 | addr_mode, | ||
| 467 | request_address, | ||
| 468 | }) | ||
| 469 | } | ||
| 470 | } | ||
diff --git a/embassy-stm32-wpan/src/mac/macros.rs b/embassy-stm32-wpan/src/mac/macros.rs new file mode 100644 index 000000000..1a988a779 --- /dev/null +++ b/embassy-stm32-wpan/src/mac/macros.rs | |||
| @@ -0,0 +1,32 @@ | |||
| 1 | #[macro_export] | ||
| 2 | macro_rules! numeric_enum { | ||
| 3 | (#[repr($repr:ident)] | ||
| 4 | $(#$attrs:tt)* $vis:vis enum $name:ident { | ||
| 5 | $($(#$enum_attrs:tt)* $enum:ident = $constant:expr),* $(,)? | ||
| 6 | } ) => { | ||
| 7 | #[repr($repr)] | ||
| 8 | $(#$attrs)* | ||
| 9 | $vis enum $name { | ||
| 10 | $($(#$enum_attrs)* $enum = $constant),* | ||
| 11 | } | ||
| 12 | |||
| 13 | impl ::core::convert::TryFrom<$repr> for $name { | ||
| 14 | type Error = (); | ||
| 15 | |||
| 16 | fn try_from(value: $repr) -> ::core::result::Result<Self, ()> { | ||
| 17 | match value { | ||
| 18 | $($constant => Ok( $name :: $enum ),)* | ||
| 19 | _ => Err(()) | ||
| 20 | } | ||
| 21 | } | ||
| 22 | } | ||
| 23 | |||
| 24 | impl ::core::convert::From<$name> for $repr { | ||
| 25 | fn from(value: $name) -> $repr { | ||
| 26 | match value { | ||
| 27 | $($name :: $enum => $constant,)* | ||
| 28 | } | ||
| 29 | } | ||
| 30 | } | ||
| 31 | } | ||
| 32 | } | ||
diff --git a/embassy-stm32-wpan/src/mac/mod.rs b/embassy-stm32-wpan/src/mac/mod.rs new file mode 100644 index 000000000..1af8fe6ba --- /dev/null +++ b/embassy-stm32-wpan/src/mac/mod.rs | |||
| @@ -0,0 +1,9 @@ | |||
| 1 | pub mod commands; | ||
| 2 | mod consts; | ||
| 3 | pub mod event; | ||
| 4 | mod helpers; | ||
| 5 | pub mod indications; | ||
| 6 | mod macros; | ||
| 7 | mod opcodes; | ||
| 8 | pub mod responses; | ||
| 9 | pub mod typedefs; | ||
diff --git a/embassy-stm32-wpan/src/mac/opcodes.rs b/embassy-stm32-wpan/src/mac/opcodes.rs new file mode 100644 index 000000000..fd7011873 --- /dev/null +++ b/embassy-stm32-wpan/src/mac/opcodes.rs | |||
| @@ -0,0 +1,92 @@ | |||
| 1 | const ST_VENDOR_OGF: u16 = 0x3F; | ||
| 2 | const MAC_802_15_4_CMD_OPCODE_OFFSET: u16 = 0x280; | ||
| 3 | |||
| 4 | const fn opcode(ocf: u16) -> isize { | ||
| 5 | ((ST_VENDOR_OGF << 9) | (MAC_802_15_4_CMD_OPCODE_OFFSET + ocf)) as isize | ||
| 6 | } | ||
| 7 | |||
| 8 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 9 | pub enum OpcodeM4ToM0 { | ||
| 10 | MlmeAssociateReq = opcode(0x00), | ||
| 11 | MlmeAssociateRes = opcode(0x01), | ||
| 12 | MlmeDisassociateReq = opcode(0x02), | ||
| 13 | MlmeGetReq = opcode(0x03), | ||
| 14 | MlmeGtsReq = opcode(0x04), | ||
| 15 | MlmeOrphanRes = opcode(0x05), | ||
| 16 | MlmeResetReq = opcode(0x06), | ||
| 17 | MlmeRxEnableReq = opcode(0x07), | ||
| 18 | MlmeScanReq = opcode(0x08), | ||
| 19 | MlmeSetReq = opcode(0x09), | ||
| 20 | MlmeStartReq = opcode(0x0A), | ||
| 21 | MlmeSyncReq = opcode(0x0B), | ||
| 22 | MlmePollReq = opcode(0x0C), | ||
| 23 | MlmeDpsReq = opcode(0x0D), | ||
| 24 | MlmeSoundingReq = opcode(0x0E), | ||
| 25 | MlmeCalibrateReq = opcode(0x0F), | ||
| 26 | McpsDataReq = opcode(0x10), | ||
| 27 | McpsPurgeReq = opcode(0x11), | ||
| 28 | } | ||
| 29 | |||
| 30 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 31 | pub enum OpcodeM0ToM4 { | ||
| 32 | MlmeAssociateCnf = 0x00, | ||
| 33 | MlmeDisassociateCnf, | ||
| 34 | MlmeGetCnf, | ||
| 35 | MlmeGtsCnf, | ||
| 36 | MlmeResetCnf, | ||
| 37 | MlmeRxEnableCnf, | ||
| 38 | MlmeScanCnf, | ||
| 39 | MlmeSetCnf, | ||
| 40 | MlmeStartCnf, | ||
| 41 | MlmePollCnf, | ||
| 42 | MlmeDpsCnf, | ||
| 43 | MlmeSoundingCnf, | ||
| 44 | MlmeCalibrateCnf, | ||
| 45 | McpsDataCnf, | ||
| 46 | McpsPurgeCnf, | ||
| 47 | MlmeAssociateInd, | ||
| 48 | MlmeDisassociateInd, | ||
| 49 | MlmeBeaconNotifyInd, | ||
| 50 | MlmeCommStatusInd, | ||
| 51 | MlmeGtsInd, | ||
| 52 | MlmeOrphanInd, | ||
| 53 | MlmeSyncLossInd, | ||
| 54 | MlmeDpsInd, | ||
| 55 | McpsDataInd, | ||
| 56 | MlmePollInd, | ||
| 57 | } | ||
| 58 | |||
| 59 | impl TryFrom<u16> for OpcodeM0ToM4 { | ||
| 60 | type Error = (); | ||
| 61 | |||
| 62 | fn try_from(value: u16) -> Result<Self, Self::Error> { | ||
| 63 | match value { | ||
| 64 | 0 => Ok(Self::MlmeAssociateCnf), | ||
| 65 | 1 => Ok(Self::MlmeDisassociateCnf), | ||
| 66 | 2 => Ok(Self::MlmeGetCnf), | ||
| 67 | 3 => Ok(Self::MlmeGtsCnf), | ||
| 68 | 4 => Ok(Self::MlmeResetCnf), | ||
| 69 | 5 => Ok(Self::MlmeRxEnableCnf), | ||
| 70 | 6 => Ok(Self::MlmeScanCnf), | ||
| 71 | 7 => Ok(Self::MlmeSetCnf), | ||
| 72 | 8 => Ok(Self::MlmeStartCnf), | ||
| 73 | 9 => Ok(Self::MlmePollCnf), | ||
| 74 | 10 => Ok(Self::MlmeDpsCnf), | ||
| 75 | 11 => Ok(Self::MlmeSoundingCnf), | ||
| 76 | 12 => Ok(Self::MlmeCalibrateCnf), | ||
| 77 | 13 => Ok(Self::McpsDataCnf), | ||
| 78 | 14 => Ok(Self::McpsPurgeCnf), | ||
| 79 | 15 => Ok(Self::MlmeAssociateInd), | ||
| 80 | 16 => Ok(Self::MlmeDisassociateInd), | ||
| 81 | 17 => Ok(Self::MlmeBeaconNotifyInd), | ||
| 82 | 18 => Ok(Self::MlmeCommStatusInd), | ||
| 83 | 19 => Ok(Self::MlmeGtsInd), | ||
| 84 | 20 => Ok(Self::MlmeOrphanInd), | ||
| 85 | 21 => Ok(Self::MlmeSyncLossInd), | ||
| 86 | 22 => Ok(Self::MlmeDpsInd), | ||
| 87 | 23 => Ok(Self::McpsDataInd), | ||
| 88 | 24 => Ok(Self::MlmePollInd), | ||
| 89 | _ => Err(()), | ||
| 90 | } | ||
| 91 | } | ||
| 92 | } | ||
diff --git a/embassy-stm32-wpan/src/mac/responses.rs b/embassy-stm32-wpan/src/mac/responses.rs new file mode 100644 index 000000000..2f6f5bf58 --- /dev/null +++ b/embassy-stm32-wpan/src/mac/responses.rs | |||
| @@ -0,0 +1,433 @@ | |||
| 1 | use super::consts::{MAX_ED_SCAN_RESULTS_SUPPORTED, MAX_PAN_DESC_SUPPORTED, MAX_SOUNDING_LIST_SUPPORTED}; | ||
| 2 | use super::event::ParseableMacEvent; | ||
| 3 | use super::helpers::to_u32; | ||
| 4 | use super::typedefs::{ | ||
| 5 | AddressMode, AssociationStatus, KeyIdMode, MacAddress, MacStatus, PanDescriptor, PanId, PibId, ScanType, | ||
| 6 | SecurityLevel, | ||
| 7 | }; | ||
| 8 | |||
| 9 | /// MLME ASSOCIATE Confirm used to inform of the initiating device whether | ||
| 10 | /// its request to associate was successful or unsuccessful | ||
| 11 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 12 | pub struct AssociateConfirm { | ||
| 13 | /// short address allocated by the coordinator on successful association | ||
| 14 | pub assoc_short_address: [u8; 2], | ||
| 15 | /// status of the association request | ||
| 16 | pub status: AssociationStatus, | ||
| 17 | /// security level to be used | ||
| 18 | pub security_level: SecurityLevel, | ||
| 19 | /// the originator of the key to be used | ||
| 20 | pub key_source: [u8; 8], | ||
| 21 | /// the mode used to identify the key to be used | ||
| 22 | pub key_id_mode: KeyIdMode, | ||
| 23 | /// the index of the key to be used | ||
| 24 | pub key_index: u8, | ||
| 25 | } | ||
| 26 | |||
| 27 | impl ParseableMacEvent for AssociateConfirm { | ||
| 28 | const SIZE: usize = 16; | ||
| 29 | |||
| 30 | fn try_parse(buf: &[u8]) -> Result<Self, ()> { | ||
| 31 | Self::validate(buf)?; | ||
| 32 | |||
| 33 | Ok(Self { | ||
| 34 | assoc_short_address: [buf[0], buf[1]], | ||
| 35 | status: AssociationStatus::try_from(buf[2])?, | ||
| 36 | security_level: SecurityLevel::try_from(buf[3])?, | ||
| 37 | key_source: [buf[4], buf[5], buf[6], buf[7], buf[8], buf[9], buf[10], buf[11]], | ||
| 38 | key_id_mode: KeyIdMode::try_from(buf[12])?, | ||
| 39 | key_index: buf[13], | ||
| 40 | }) | ||
| 41 | } | ||
| 42 | } | ||
| 43 | |||
| 44 | /// MLME DISASSOCIATE Confirm used to send disassociation Confirmation to the application. | ||
| 45 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 46 | pub struct DisassociateConfirm { | ||
| 47 | /// status of the disassociation attempt | ||
| 48 | pub status: MacStatus, | ||
| 49 | /// device addressing mode used | ||
| 50 | pub device_addr_mode: AddressMode, | ||
| 51 | /// the identifier of the PAN of the device | ||
| 52 | pub device_pan_id: PanId, | ||
| 53 | /// device address | ||
| 54 | pub device_address: MacAddress, | ||
| 55 | } | ||
| 56 | |||
| 57 | impl ParseableMacEvent for DisassociateConfirm { | ||
| 58 | const SIZE: usize = 12; | ||
| 59 | |||
| 60 | fn try_parse(buf: &[u8]) -> Result<Self, ()> { | ||
| 61 | Self::validate(buf)?; | ||
| 62 | |||
| 63 | let device_addr_mode = AddressMode::try_from(buf[1])?; | ||
| 64 | let device_address = match device_addr_mode { | ||
| 65 | AddressMode::NoAddress => MacAddress { short: [0, 0] }, | ||
| 66 | AddressMode::Reserved => MacAddress { short: [0, 0] }, | ||
| 67 | AddressMode::Short => MacAddress { | ||
| 68 | short: [buf[4], buf[5]], | ||
| 69 | }, | ||
| 70 | AddressMode::Extended => MacAddress { | ||
| 71 | extended: [buf[4], buf[5], buf[6], buf[7], buf[8], buf[9], buf[10], buf[11]], | ||
| 72 | }, | ||
| 73 | }; | ||
| 74 | |||
| 75 | Ok(Self { | ||
| 76 | status: MacStatus::try_from(buf[0])?, | ||
| 77 | device_addr_mode, | ||
| 78 | device_pan_id: PanId([buf[2], buf[3]]), | ||
| 79 | device_address, | ||
| 80 | }) | ||
| 81 | } | ||
| 82 | } | ||
| 83 | |||
| 84 | /// MLME GET Confirm which requests information about a given PIB attribute | ||
| 85 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 86 | pub struct GetConfirm { | ||
| 87 | /// The pointer to the value of the PIB attribute attempted to read | ||
| 88 | pub pib_attribute_value_ptr: *const u8, | ||
| 89 | /// Status of the GET attempt | ||
| 90 | pub status: MacStatus, | ||
| 91 | /// The name of the PIB attribute attempted to read | ||
| 92 | pub pib_attribute: PibId, | ||
| 93 | /// The lenght of the PIB attribute Value return | ||
| 94 | pub pib_attribute_value_len: u8, | ||
| 95 | } | ||
| 96 | |||
| 97 | impl ParseableMacEvent for GetConfirm { | ||
| 98 | const SIZE: usize = 8; | ||
| 99 | |||
| 100 | fn try_parse(buf: &[u8]) -> Result<Self, ()> { | ||
| 101 | Self::validate(buf)?; | ||
| 102 | |||
| 103 | let address = to_u32(&buf[0..4]); | ||
| 104 | |||
| 105 | Ok(Self { | ||
| 106 | pib_attribute_value_ptr: address as *const u8, | ||
| 107 | status: MacStatus::try_from(buf[4])?, | ||
| 108 | pib_attribute: PibId::try_from(buf[5])?, | ||
| 109 | pib_attribute_value_len: buf[6], | ||
| 110 | }) | ||
| 111 | } | ||
| 112 | } | ||
| 113 | |||
| 114 | /// MLME GTS Confirm which eports the results of a request to allocate a new GTS | ||
| 115 | /// or to deallocate an existing GTS | ||
| 116 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 117 | pub struct GtsConfirm { | ||
| 118 | /// The characteristics of the GTS | ||
| 119 | pub gts_characteristics: u8, | ||
| 120 | /// The status of the GTS reques | ||
| 121 | pub status: MacStatus, | ||
| 122 | } | ||
| 123 | |||
| 124 | impl ParseableMacEvent for GtsConfirm { | ||
| 125 | const SIZE: usize = 4; | ||
| 126 | |||
| 127 | fn try_parse(buf: &[u8]) -> Result<Self, ()> { | ||
| 128 | Self::validate(buf)?; | ||
| 129 | |||
| 130 | Ok(Self { | ||
| 131 | gts_characteristics: buf[0], | ||
| 132 | status: MacStatus::try_from(buf[1])?, | ||
| 133 | }) | ||
| 134 | } | ||
| 135 | } | ||
| 136 | |||
| 137 | /// MLME RESET Confirm which is used to report the results of the reset operation | ||
| 138 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 139 | pub struct ResetConfirm { | ||
| 140 | /// The result of the reset operation | ||
| 141 | status: MacStatus, | ||
| 142 | } | ||
| 143 | |||
| 144 | impl ParseableMacEvent for ResetConfirm { | ||
| 145 | const SIZE: usize = 4; | ||
| 146 | |||
| 147 | fn try_parse(buf: &[u8]) -> Result<Self, ()> { | ||
| 148 | Self::validate(buf)?; | ||
| 149 | |||
| 150 | Ok(Self { | ||
| 151 | status: MacStatus::try_from(buf[0])?, | ||
| 152 | }) | ||
| 153 | } | ||
| 154 | } | ||
| 155 | |||
| 156 | /// MLME RX ENABLE Confirm which is used to report the results of the attempt | ||
| 157 | /// to enable or disable the receiver | ||
| 158 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 159 | pub struct RxEnableConfirm { | ||
| 160 | /// Result of the request to enable or disable the receiver | ||
| 161 | status: MacStatus, | ||
| 162 | } | ||
| 163 | |||
| 164 | impl ParseableMacEvent for RxEnableConfirm { | ||
| 165 | const SIZE: usize = 4; | ||
| 166 | |||
| 167 | fn try_parse(buf: &[u8]) -> Result<Self, ()> { | ||
| 168 | Self::validate(buf)?; | ||
| 169 | |||
| 170 | Ok(Self { | ||
| 171 | status: MacStatus::try_from(buf[0])?, | ||
| 172 | }) | ||
| 173 | } | ||
| 174 | } | ||
| 175 | |||
| 176 | /// MLME SCAN Confirm which is used to report the result of the channel scan request | ||
| 177 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 178 | pub struct ScanConfirm { | ||
| 179 | /// Status of the scan request | ||
| 180 | pub status: MacStatus, | ||
| 181 | /// The type of scan performed | ||
| 182 | pub scan_type: ScanType, | ||
| 183 | /// Channel page on which the scan was performed | ||
| 184 | pub channel_page: u8, | ||
| 185 | /// Channels given in the request which were not scanned | ||
| 186 | pub unscanned_channels: [u8; 4], | ||
| 187 | /// Number of elements returned in the appropriate result lists | ||
| 188 | pub result_list_size: u8, | ||
| 189 | /// List of energy measurements | ||
| 190 | pub energy_detect_list: [u8; MAX_ED_SCAN_RESULTS_SUPPORTED], | ||
| 191 | /// List of PAN descriptors | ||
| 192 | pub pan_descriptor_list: [PanDescriptor; MAX_PAN_DESC_SUPPORTED], | ||
| 193 | /// Categorization of energy detected in channel | ||
| 194 | pub detected_category: u8, | ||
| 195 | /// For UWB PHYs, the list of energy measurements taken | ||
| 196 | pub uwb_energy_detect_list: [u8; MAX_ED_SCAN_RESULTS_SUPPORTED], | ||
| 197 | } | ||
| 198 | |||
| 199 | impl ParseableMacEvent for ScanConfirm { | ||
| 200 | const SIZE: usize = 185; | ||
| 201 | |||
| 202 | fn try_parse(buf: &[u8]) -> Result<Self, ()> { | ||
| 203 | // TODO: this is unchecked | ||
| 204 | |||
| 205 | Self::validate(buf)?; | ||
| 206 | |||
| 207 | let mut energy_detect_list = [0; MAX_ED_SCAN_RESULTS_SUPPORTED]; | ||
| 208 | energy_detect_list.copy_from_slice(&buf[8..24]); | ||
| 209 | |||
| 210 | let pan_descriptor_list = [ | ||
| 211 | PanDescriptor::try_from(&buf[24..46])?, | ||
| 212 | PanDescriptor::try_from(&buf[46..68])?, | ||
| 213 | PanDescriptor::try_from(&buf[68..90])?, | ||
| 214 | PanDescriptor::try_from(&buf[90..102])?, | ||
| 215 | PanDescriptor::try_from(&buf[102..124])?, | ||
| 216 | PanDescriptor::try_from(&buf[124..146])?, | ||
| 217 | ]; | ||
| 218 | |||
| 219 | let mut uwb_energy_detect_list = [0; MAX_ED_SCAN_RESULTS_SUPPORTED]; | ||
| 220 | uwb_energy_detect_list.copy_from_slice(&buf[147..163]); | ||
| 221 | |||
| 222 | Ok(Self { | ||
| 223 | status: MacStatus::try_from(buf[0])?, | ||
| 224 | scan_type: ScanType::try_from(buf[1])?, | ||
| 225 | channel_page: buf[2], | ||
| 226 | unscanned_channels: [buf[3], buf[4], buf[5], buf[6]], | ||
| 227 | result_list_size: buf[7], | ||
| 228 | energy_detect_list, | ||
| 229 | pan_descriptor_list, | ||
| 230 | detected_category: buf[146], | ||
| 231 | uwb_energy_detect_list, | ||
| 232 | }) | ||
| 233 | } | ||
| 234 | } | ||
| 235 | |||
| 236 | /// MLME SET Confirm which reports the result of an attempt to write a value to a PIB attribute | ||
| 237 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 238 | pub struct SetConfirm { | ||
| 239 | /// The result of the set operation | ||
| 240 | pub status: MacStatus, | ||
| 241 | /// The name of the PIB attribute that was written | ||
| 242 | pub pin_attribute: PibId, | ||
| 243 | } | ||
| 244 | |||
| 245 | impl ParseableMacEvent for SetConfirm { | ||
| 246 | const SIZE: usize = 4; | ||
| 247 | |||
| 248 | fn try_parse(buf: &[u8]) -> Result<Self, ()> { | ||
| 249 | Self::validate(buf)?; | ||
| 250 | |||
| 251 | Ok(Self { | ||
| 252 | status: MacStatus::try_from(buf[0])?, | ||
| 253 | pin_attribute: PibId::try_from(buf[1])?, | ||
| 254 | }) | ||
| 255 | } | ||
| 256 | } | ||
| 257 | |||
| 258 | /// MLME START Confirm which is used to report the results of the attempt to | ||
| 259 | /// start using a new superframe configuration | ||
| 260 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 261 | pub struct StartConfirm { | ||
| 262 | /// Result of the attempt to start using an updated superframe configuration | ||
| 263 | pub status: MacStatus, | ||
| 264 | } | ||
| 265 | |||
| 266 | impl ParseableMacEvent for StartConfirm { | ||
| 267 | const SIZE: usize = 4; | ||
| 268 | |||
| 269 | fn try_parse(buf: &[u8]) -> Result<Self, ()> { | ||
| 270 | Self::validate(buf)?; | ||
| 271 | |||
| 272 | Ok(Self { | ||
| 273 | status: MacStatus::try_from(buf[0])?, | ||
| 274 | }) | ||
| 275 | } | ||
| 276 | } | ||
| 277 | |||
| 278 | /// MLME POLL Confirm which is used to report the result of a request to poll the coordinator for data | ||
| 279 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 280 | pub struct PollConfirm { | ||
| 281 | /// The status of the data request | ||
| 282 | pub status: MacStatus, | ||
| 283 | } | ||
| 284 | |||
| 285 | impl ParseableMacEvent for PollConfirm { | ||
| 286 | const SIZE: usize = 4; | ||
| 287 | |||
| 288 | fn try_parse(buf: &[u8]) -> Result<Self, ()> { | ||
| 289 | Self::validate(buf)?; | ||
| 290 | |||
| 291 | Ok(Self { | ||
| 292 | status: MacStatus::try_from(buf[0])?, | ||
| 293 | }) | ||
| 294 | } | ||
| 295 | } | ||
| 296 | |||
| 297 | /// MLME DPS Confirm which reports the results of the attempt to enable or disable the DPS | ||
| 298 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 299 | pub struct DpsConfirm { | ||
| 300 | /// The status of the DPS request | ||
| 301 | pub status: MacStatus, | ||
| 302 | } | ||
| 303 | |||
| 304 | impl ParseableMacEvent for DpsConfirm { | ||
| 305 | const SIZE: usize = 4; | ||
| 306 | |||
| 307 | fn try_parse(buf: &[u8]) -> Result<Self, ()> { | ||
| 308 | Self::validate(buf)?; | ||
| 309 | |||
| 310 | Ok(Self { | ||
| 311 | status: MacStatus::try_from(buf[0])?, | ||
| 312 | }) | ||
| 313 | } | ||
| 314 | } | ||
| 315 | |||
| 316 | /// MLME SOUNDING Confirm which reports the result of a request to the PHY to provide | ||
| 317 | /// channel sounding information | ||
| 318 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 319 | pub struct SoundingConfirm { | ||
| 320 | /// Results of the sounding measurement | ||
| 321 | sounding_list: [u8; MAX_SOUNDING_LIST_SUPPORTED], | ||
| 322 | } | ||
| 323 | |||
| 324 | impl ParseableMacEvent for SoundingConfirm { | ||
| 325 | const SIZE: usize = 1; | ||
| 326 | |||
| 327 | fn try_parse(buf: &[u8]) -> Result<Self, ()> { | ||
| 328 | Self::validate(buf)?; | ||
| 329 | |||
| 330 | let mut sounding_list = [0u8; MAX_SOUNDING_LIST_SUPPORTED]; | ||
| 331 | sounding_list[..buf.len()].copy_from_slice(buf); | ||
| 332 | |||
| 333 | Ok(Self { sounding_list }) | ||
| 334 | } | ||
| 335 | } | ||
| 336 | |||
| 337 | /// MLME CALIBRATE Confirm which reports the result of a request to the PHY | ||
| 338 | /// to provide internal propagation path information | ||
| 339 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 340 | pub struct CalibrateConfirm { | ||
| 341 | /// The status of the attempt to return sounding data | ||
| 342 | pub status: MacStatus, | ||
| 343 | /// A count of the propagation time from the ranging counter | ||
| 344 | /// to the transmit antenna | ||
| 345 | pub cal_tx_rmaker_offset: u32, | ||
| 346 | /// A count of the propagation time from the receive antenna | ||
| 347 | /// to the ranging counter | ||
| 348 | pub cal_rx_rmaker_offset: u32, | ||
| 349 | } | ||
| 350 | |||
| 351 | impl ParseableMacEvent for CalibrateConfirm { | ||
| 352 | const SIZE: usize = 12; | ||
| 353 | |||
| 354 | fn try_parse(buf: &[u8]) -> Result<Self, ()> { | ||
| 355 | Self::validate(buf)?; | ||
| 356 | |||
| 357 | Ok(Self { | ||
| 358 | status: MacStatus::try_from(buf[0])?, | ||
| 359 | // 3 byte stuffing | ||
| 360 | cal_tx_rmaker_offset: to_u32(&buf[4..8]), | ||
| 361 | cal_rx_rmaker_offset: to_u32(&buf[8..12]), | ||
| 362 | }) | ||
| 363 | } | ||
| 364 | } | ||
| 365 | |||
| 366 | /// MCPS DATA Confirm which will be used for reporting the results of | ||
| 367 | /// MAC data related requests from the application | ||
| 368 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 369 | pub struct DataConfirm { | ||
| 370 | /// The handle associated with the MSDU being confirmed | ||
| 371 | pub msdu_handle: u8, | ||
| 372 | /// The time, in symbols, at which the data were transmitted | ||
| 373 | pub time_stamp: [u8; 4], | ||
| 374 | /// ranging status | ||
| 375 | pub ranging_received: u8, | ||
| 376 | /// The status of the last MSDU transmission | ||
| 377 | pub status: MacStatus, | ||
| 378 | /// time units corresponding to an RMARKER at the antenna at | ||
| 379 | /// the beginning of a ranging exchange | ||
| 380 | pub ranging_counter_start: u32, | ||
| 381 | /// time units corresponding to an RMARKER at the antenna | ||
| 382 | /// at the end of a ranging exchange | ||
| 383 | pub ranging_counter_stop: u32, | ||
| 384 | /// time units in a message exchange over which the tracking offset was measured | ||
| 385 | pub ranging_tracking_interval: u32, | ||
| 386 | /// time units slipped or advanced by the radio tracking system | ||
| 387 | pub ranging_offset: u32, | ||
| 388 | /// The FoM characterizing the ranging measurement | ||
| 389 | pub ranging_fom: u8, | ||
| 390 | } | ||
| 391 | |||
| 392 | impl ParseableMacEvent for DataConfirm { | ||
| 393 | const SIZE: usize = 28; | ||
| 394 | |||
| 395 | fn try_parse(buf: &[u8]) -> Result<Self, ()> { | ||
| 396 | Self::validate(buf)?; | ||
| 397 | |||
| 398 | Ok(Self { | ||
| 399 | msdu_handle: buf[0], | ||
| 400 | time_stamp: [buf[1], buf[2], buf[3], buf[4]], | ||
| 401 | ranging_received: buf[5], | ||
| 402 | status: MacStatus::try_from(buf[6])?, | ||
| 403 | ranging_counter_start: to_u32(&buf[7..11]), | ||
| 404 | ranging_counter_stop: to_u32(&buf[11..15]), | ||
| 405 | ranging_tracking_interval: to_u32(&buf[15..19]), | ||
| 406 | ranging_offset: to_u32(&buf[19..23]), | ||
| 407 | ranging_fom: buf[24], | ||
| 408 | }) | ||
| 409 | } | ||
| 410 | } | ||
| 411 | |||
| 412 | /// MCPS PURGE Confirm which will be used by the MAC to notify the application of | ||
| 413 | /// the status of its request to purge an MSDU from the transaction queue | ||
| 414 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 415 | pub struct PurgeConfirm { | ||
| 416 | /// Handle associated with the MSDU requested to be purged from the transaction queue | ||
| 417 | pub msdu_handle: u8, | ||
| 418 | /// The status of the request | ||
| 419 | pub status: MacStatus, | ||
| 420 | } | ||
| 421 | |||
| 422 | impl ParseableMacEvent for PurgeConfirm { | ||
| 423 | const SIZE: usize = 4; | ||
| 424 | |||
| 425 | fn try_parse(buf: &[u8]) -> Result<Self, ()> { | ||
| 426 | Self::validate(buf)?; | ||
| 427 | |||
| 428 | Ok(Self { | ||
| 429 | msdu_handle: buf[0], | ||
| 430 | status: MacStatus::try_from(buf[1])?, | ||
| 431 | }) | ||
| 432 | } | ||
| 433 | } | ||
diff --git a/embassy-stm32-wpan/src/mac/typedefs.rs b/embassy-stm32-wpan/src/mac/typedefs.rs new file mode 100644 index 000000000..30c7731b2 --- /dev/null +++ b/embassy-stm32-wpan/src/mac/typedefs.rs | |||
| @@ -0,0 +1,363 @@ | |||
| 1 | use crate::numeric_enum; | ||
| 2 | |||
| 3 | #[derive(Debug)] | ||
| 4 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 5 | pub enum MacError { | ||
| 6 | Error = 0x01, | ||
| 7 | NotImplemented = 0x02, | ||
| 8 | NotSupported = 0x03, | ||
| 9 | HardwareNotSupported = 0x04, | ||
| 10 | Undefined = 0x05, | ||
| 11 | } | ||
| 12 | |||
| 13 | impl From<u8> for MacError { | ||
| 14 | fn from(value: u8) -> Self { | ||
| 15 | match value { | ||
| 16 | 0x01 => Self::Error, | ||
| 17 | 0x02 => Self::NotImplemented, | ||
| 18 | 0x03 => Self::NotSupported, | ||
| 19 | 0x04 => Self::HardwareNotSupported, | ||
| 20 | 0x05 => Self::Undefined, | ||
| 21 | _ => Self::Undefined, | ||
| 22 | } | ||
| 23 | } | ||
| 24 | } | ||
| 25 | |||
| 26 | numeric_enum! { | ||
| 27 | #[repr(u8)] | ||
| 28 | #[derive(Debug, Default)] | ||
| 29 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 30 | pub enum MacStatus { | ||
| 31 | #[default] | ||
| 32 | Success = 0x00, | ||
| 33 | Failure = 0xFF | ||
| 34 | } | ||
| 35 | } | ||
| 36 | |||
| 37 | numeric_enum! { | ||
| 38 | #[repr(u8)] | ||
| 39 | /// this enum contains all the MAC PIB Ids | ||
| 40 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 41 | pub enum PibId { | ||
| 42 | // PHY | ||
| 43 | CurrentChannel = 0x00, | ||
| 44 | ChannelsSupported = 0x01, | ||
| 45 | TransmitPower = 0x02, | ||
| 46 | CCAMode = 0x03, | ||
| 47 | CurrentPage = 0x04, | ||
| 48 | MaxFrameDuration = 0x05, | ||
| 49 | SHRDuration = 0x06, | ||
| 50 | SymbolsPerOctet = 0x07, | ||
| 51 | |||
| 52 | // MAC | ||
| 53 | AckWaitDuration = 0x40, | ||
| 54 | AssociationPermit = 0x41, | ||
| 55 | AutoRequest = 0x42, | ||
| 56 | BeaconPayload = 0x45, | ||
| 57 | BeaconPayloadLength = 0x46, | ||
| 58 | BeaconOrder = 0x47, | ||
| 59 | Bsn = 0x49, | ||
| 60 | CoordExtendedAdddress = 0x4A, | ||
| 61 | CoordShortAddress = 0x4B, | ||
| 62 | Dsn = 0x4C, | ||
| 63 | MaxFrameTotalWaitTime = 0x58, | ||
| 64 | MaxFrameRetries = 0x59, | ||
| 65 | PanId = 0x50, | ||
| 66 | ResponseWaitTime = 0x5A, | ||
| 67 | RxOnWhenIdle = 0x52, | ||
| 68 | SecurityEnabled = 0x5D, | ||
| 69 | ShortAddress = 0x53, | ||
| 70 | SuperframeOrder = 0x54, | ||
| 71 | TimestampSupported = 0x5C, | ||
| 72 | TransactionPersistenceTime = 0x55, | ||
| 73 | MaxBe = 0x57, | ||
| 74 | LifsPeriod = 0x5E, | ||
| 75 | SifsPeriod = 0x5F, | ||
| 76 | MaxCsmaBackoffs = 0x4E, | ||
| 77 | MinBe = 0x4F, | ||
| 78 | PanCoordinator = 0x10, | ||
| 79 | AssocPanCoordinator = 0x11, | ||
| 80 | ExtendedAddress = 0x6F, | ||
| 81 | AclEntryDescriptor = 0x70, | ||
| 82 | AclEntryDescriptorSize = 0x71, | ||
| 83 | DefaultSecurity = 0x72, | ||
| 84 | DefaultSecurityMaterialLength = 0x73, | ||
| 85 | DefaultSecurityMaterial = 0x74, | ||
| 86 | DefaultSecuritySuite = 0x75, | ||
| 87 | SecurityMode = 0x76, | ||
| 88 | CurrentAclEntries = 0x80, | ||
| 89 | DefaultSecurityExtendedAddress = 0x81, | ||
| 90 | AssociatedPanCoordinator = 0x56, | ||
| 91 | PromiscuousMode = 0x51, | ||
| 92 | } | ||
| 93 | } | ||
| 94 | |||
| 95 | numeric_enum! { | ||
| 96 | #[repr(u8)] | ||
| 97 | #[derive(Default, Clone, Copy)] | ||
| 98 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 99 | pub enum AddressMode { | ||
| 100 | #[default] | ||
| 101 | NoAddress = 0x00, | ||
| 102 | Reserved = 0x01, | ||
| 103 | Short = 0x02, | ||
| 104 | Extended = 0x03, | ||
| 105 | } | ||
| 106 | } | ||
| 107 | |||
| 108 | #[derive(Clone, Copy)] | ||
| 109 | pub union MacAddress { | ||
| 110 | pub short: [u8; 2], | ||
| 111 | pub extended: [u8; 8], | ||
| 112 | } | ||
| 113 | |||
| 114 | #[cfg(feature = "defmt")] | ||
| 115 | impl defmt::Format for MacAddress { | ||
| 116 | fn format(&self, fmt: defmt::Formatter) { | ||
| 117 | unsafe { | ||
| 118 | defmt::write!( | ||
| 119 | fmt, | ||
| 120 | "MacAddress {{ short: {}, extended: {} }}", | ||
| 121 | self.short, | ||
| 122 | self.extended | ||
| 123 | ) | ||
| 124 | } | ||
| 125 | } | ||
| 126 | } | ||
| 127 | |||
| 128 | impl Default for MacAddress { | ||
| 129 | fn default() -> Self { | ||
| 130 | Self { short: [0, 0] } | ||
| 131 | } | ||
| 132 | } | ||
| 133 | |||
| 134 | impl MacAddress { | ||
| 135 | pub const BROADCAST: Self = Self { short: [0xFF, 0xFF] }; | ||
| 136 | } | ||
| 137 | |||
| 138 | impl TryFrom<&[u8]> for MacAddress { | ||
| 139 | type Error = (); | ||
| 140 | |||
| 141 | fn try_from(buf: &[u8]) -> Result<Self, Self::Error> { | ||
| 142 | const SIZE: usize = 8; | ||
| 143 | if buf.len() < SIZE { | ||
| 144 | return Err(()); | ||
| 145 | } | ||
| 146 | |||
| 147 | Ok(Self { | ||
| 148 | extended: [buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]], | ||
| 149 | }) | ||
| 150 | } | ||
| 151 | } | ||
| 152 | |||
| 153 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 154 | pub struct GtsCharacteristics { | ||
| 155 | pub fields: u8, | ||
| 156 | } | ||
| 157 | |||
| 158 | /// MAC PAN Descriptor which contains the network details of the device from | ||
| 159 | /// which the beacon is received | ||
| 160 | #[derive(Default, Clone, Copy)] | ||
| 161 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 162 | pub struct PanDescriptor { | ||
| 163 | /// PAN identifier of the coordinator | ||
| 164 | pub coord_pan_id: PanId, | ||
| 165 | /// Coordinator addressing mode | ||
| 166 | pub coord_addr_mode: AddressMode, | ||
| 167 | /// The current logical channel occupied by the network | ||
| 168 | pub logical_channel: MacChannel, | ||
| 169 | /// Coordinator address | ||
| 170 | pub coord_addr: MacAddress, | ||
| 171 | /// The current channel page occupied by the network | ||
| 172 | pub channel_page: u8, | ||
| 173 | /// PAN coordinator is accepting GTS requests or not | ||
| 174 | pub gts_permit: bool, | ||
| 175 | /// Superframe specification as specified in the received beacon frame | ||
| 176 | pub superframe_spec: [u8; 2], | ||
| 177 | /// The time at which the beacon frame was received, in symbols | ||
| 178 | pub time_stamp: [u8; 4], | ||
| 179 | /// The LQI at which the network beacon was received | ||
| 180 | pub link_quality: u8, | ||
| 181 | /// Security level purportedly used by the received beacon frame | ||
| 182 | pub security_level: u8, | ||
| 183 | } | ||
| 184 | |||
| 185 | impl TryFrom<&[u8]> for PanDescriptor { | ||
| 186 | type Error = (); | ||
| 187 | |||
| 188 | fn try_from(buf: &[u8]) -> Result<Self, Self::Error> { | ||
| 189 | const SIZE: usize = 22; | ||
| 190 | if buf.len() < SIZE { | ||
| 191 | return Err(()); | ||
| 192 | } | ||
| 193 | |||
| 194 | let coord_addr_mode = AddressMode::try_from(buf[2])?; | ||
| 195 | let coord_addr = match coord_addr_mode { | ||
| 196 | AddressMode::NoAddress => MacAddress { short: [0, 0] }, | ||
| 197 | AddressMode::Reserved => MacAddress { short: [0, 0] }, | ||
| 198 | AddressMode::Short => MacAddress { | ||
| 199 | short: [buf[4], buf[5]], | ||
| 200 | }, | ||
| 201 | AddressMode::Extended => MacAddress { | ||
| 202 | extended: [buf[4], buf[5], buf[6], buf[7], buf[8], buf[9], buf[10], buf[11]], | ||
| 203 | }, | ||
| 204 | }; | ||
| 205 | |||
| 206 | Ok(Self { | ||
| 207 | coord_pan_id: PanId([buf[0], buf[1]]), | ||
| 208 | coord_addr_mode, | ||
| 209 | logical_channel: MacChannel::try_from(buf[3])?, | ||
| 210 | coord_addr, | ||
| 211 | channel_page: buf[12], | ||
| 212 | gts_permit: buf[13] != 0, | ||
| 213 | superframe_spec: [buf[14], buf[15]], | ||
| 214 | time_stamp: [buf[16], buf[17], buf[18], buf[19]], | ||
| 215 | link_quality: buf[20], | ||
| 216 | security_level: buf[21], | ||
| 217 | // 2 byte stuffing | ||
| 218 | }) | ||
| 219 | } | ||
| 220 | } | ||
| 221 | |||
| 222 | numeric_enum! { | ||
| 223 | #[repr(u8)] | ||
| 224 | #[derive(Default, Clone, Copy)] | ||
| 225 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 226 | /// Building wireless applications with STM32WB series MCUs - Application note 13.10.3 | ||
| 227 | pub enum MacChannel { | ||
| 228 | Channel11 = 0x0B, | ||
| 229 | Channel12 = 0x0C, | ||
| 230 | Channel13 = 0x0D, | ||
| 231 | Channel14 = 0x0E, | ||
| 232 | Channel15 = 0x0F, | ||
| 233 | #[default] | ||
| 234 | Channel16 = 0x10, | ||
| 235 | Channel17 = 0x11, | ||
| 236 | Channel18 = 0x12, | ||
| 237 | Channel19 = 0x13, | ||
| 238 | Channel20 = 0x14, | ||
| 239 | Channel21 = 0x15, | ||
| 240 | Channel22 = 0x16, | ||
| 241 | Channel23 = 0x17, | ||
| 242 | Channel24 = 0x18, | ||
| 243 | Channel25 = 0x19, | ||
| 244 | Channel26 = 0x1A, | ||
| 245 | } | ||
| 246 | } | ||
| 247 | |||
| 248 | #[cfg(not(feature = "defmt"))] | ||
| 249 | bitflags::bitflags! { | ||
| 250 | pub struct Capabilities: u8 { | ||
| 251 | /// 1 if the device is capabaleof becoming a PAN coordinator | ||
| 252 | const IS_COORDINATOR_CAPABLE = 0b00000001; | ||
| 253 | /// 1 if the device is an FFD, 0 if it is an RFD | ||
| 254 | const IS_FFD = 0b00000010; | ||
| 255 | /// 1 if the device is receiving power from mains, 0 if it is battery-powered | ||
| 256 | const IS_MAINS_POWERED = 0b00000100; | ||
| 257 | /// 1 if the device does not disable its receiver to conserver power during idle periods | ||
| 258 | const RECEIVER_ON_WHEN_IDLE = 0b00001000; | ||
| 259 | // 0b00010000 reserved | ||
| 260 | // 0b00100000 reserved | ||
| 261 | /// 1 if the device is capable of sending and receiving secured MAC frames | ||
| 262 | const IS_SECURE = 0b01000000; | ||
| 263 | /// 1 if the device wishes the coordinator to allocate a short address as a result of the association | ||
| 264 | const ALLOCATE_ADDRESS = 0b10000000; | ||
| 265 | } | ||
| 266 | } | ||
| 267 | |||
| 268 | #[cfg(feature = "defmt")] | ||
| 269 | defmt::bitflags! { | ||
| 270 | pub struct Capabilities: u8 { | ||
| 271 | /// 1 if the device is capabaleof becoming a PAN coordinator | ||
| 272 | const IS_COORDINATOR_CAPABLE = 0b00000001; | ||
| 273 | /// 1 if the device is an FFD, 0 if it is an RFD | ||
| 274 | const IS_FFD = 0b00000010; | ||
| 275 | /// 1 if the device is receiving power from mains, 0 if it is battery-powered | ||
| 276 | const IS_MAINS_POWERED = 0b00000100; | ||
| 277 | /// 1 if the device does not disable its receiver to conserver power during idle periods | ||
| 278 | const RECEIVER_ON_WHEN_IDLE = 0b00001000; | ||
| 279 | // 0b00010000 reserved | ||
| 280 | // 0b00100000 reserved | ||
| 281 | /// 1 if the device is capable of sending and receiving secured MAC frames | ||
| 282 | const IS_SECURE = 0b01000000; | ||
| 283 | /// 1 if the device wishes the coordinator to allocate a short address as a result of the association | ||
| 284 | const ALLOCATE_ADDRESS = 0b10000000; | ||
| 285 | } | ||
| 286 | } | ||
| 287 | |||
| 288 | numeric_enum! { | ||
| 289 | #[repr(u8)] | ||
| 290 | #[derive(Default, Clone, Copy)] | ||
| 291 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 292 | pub enum KeyIdMode { | ||
| 293 | #[default] | ||
| 294 | /// the key is determined implicitly from the originator and recipient(s) of the frame | ||
| 295 | Implicite = 0x00, | ||
| 296 | /// the key is determined explicitly using a 1 bytes key source and a 1 byte key index | ||
| 297 | Explicite1Byte = 0x01, | ||
| 298 | /// the key is determined explicitly using a 4 bytes key source and a 1 byte key index | ||
| 299 | Explicite4Byte = 0x02, | ||
| 300 | /// the key is determined explicitly using a 8 bytes key source and a 1 byte key index | ||
| 301 | Explicite8Byte = 0x03, | ||
| 302 | } | ||
| 303 | } | ||
| 304 | |||
| 305 | numeric_enum! { | ||
| 306 | #[repr(u8)] | ||
| 307 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 308 | pub enum AssociationStatus { | ||
| 309 | /// Association successful | ||
| 310 | Success = 0x00, | ||
| 311 | /// PAN at capacity | ||
| 312 | PanAtCapacity = 0x01, | ||
| 313 | /// PAN access denied | ||
| 314 | PanAccessDenied = 0x02 | ||
| 315 | } | ||
| 316 | } | ||
| 317 | |||
| 318 | numeric_enum! { | ||
| 319 | #[repr(u8)] | ||
| 320 | #[derive(Clone, Copy)] | ||
| 321 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 322 | pub enum DisassociationReason { | ||
| 323 | /// The coordinator wishes the device to leave the PAN. | ||
| 324 | CoordRequested = 0x01, | ||
| 325 | /// The device wishes to leave the PAN. | ||
| 326 | DeviceRequested = 0x02, | ||
| 327 | } | ||
| 328 | } | ||
| 329 | |||
| 330 | numeric_enum! { | ||
| 331 | #[repr(u8)] | ||
| 332 | #[derive(Default, Clone, Copy)] | ||
| 333 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 334 | pub enum SecurityLevel { | ||
| 335 | /// MAC Unsecured Mode Security | ||
| 336 | #[default] | ||
| 337 | Unsecure = 0x00, | ||
| 338 | /// MAC ACL Mode Security | ||
| 339 | AclMode = 0x01, | ||
| 340 | /// MAC Secured Mode Security | ||
| 341 | Secured = 0x02, | ||
| 342 | } | ||
| 343 | } | ||
| 344 | |||
| 345 | numeric_enum! { | ||
| 346 | #[repr(u8)] | ||
| 347 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 348 | pub enum ScanType { | ||
| 349 | EdScan = 0x00, | ||
| 350 | Active = 0x01, | ||
| 351 | Passive = 0x02, | ||
| 352 | Orphan = 0x03 | ||
| 353 | } | ||
| 354 | } | ||
| 355 | |||
| 356 | /// newtype for Pan Id | ||
| 357 | #[derive(Default, Clone, Copy)] | ||
| 358 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 359 | pub struct PanId(pub [u8; 2]); | ||
| 360 | |||
| 361 | impl PanId { | ||
| 362 | pub const BROADCAST: Self = Self([0xFF, 0xFF]); | ||
| 363 | } | ||
diff --git a/embassy-stm32-wpan/src/sub/mac.rs b/embassy-stm32-wpan/src/sub/mac.rs index fd8af8609..4893cb47b 100644 --- a/embassy-stm32-wpan/src/sub/mac.rs +++ b/embassy-stm32-wpan/src/sub/mac.rs | |||
| @@ -11,9 +11,10 @@ use embassy_sync::waitqueue::AtomicWaker; | |||
| 11 | use crate::cmd::CmdPacket; | 11 | use crate::cmd::CmdPacket; |
| 12 | use crate::consts::TlPacketType; | 12 | use crate::consts::TlPacketType; |
| 13 | use crate::evt::{EvtBox, EvtPacket}; | 13 | use crate::evt::{EvtBox, EvtPacket}; |
| 14 | use crate::tables::{ | 14 | use crate::mac::commands::MacCommand; |
| 15 | Mac802_15_4Table, MAC_802_15_4_CMD_BUFFER, MAC_802_15_4_NOTIF_RSP_EVT_BUFFER, TL_MAC_802_15_4_TABLE, | 15 | use crate::mac::event::MacEvent; |
| 16 | }; | 16 | use crate::mac::typedefs::MacError; |
| 17 | use crate::tables::{MAC_802_15_4_CMD_BUFFER, MAC_802_15_4_NOTIF_RSP_EVT_BUFFER}; | ||
| 17 | use crate::{channels, evt}; | 18 | use crate::{channels, evt}; |
| 18 | 19 | ||
| 19 | static MAC_WAKER: AtomicWaker = AtomicWaker::new(); | 20 | static MAC_WAKER: AtomicWaker = AtomicWaker::new(); |
| @@ -25,21 +26,13 @@ pub struct Mac { | |||
| 25 | 26 | ||
| 26 | impl Mac { | 27 | impl Mac { |
| 27 | pub(crate) fn new() -> Self { | 28 | pub(crate) fn new() -> Self { |
| 28 | unsafe { | ||
| 29 | TL_MAC_802_15_4_TABLE.as_mut_ptr().write_volatile(Mac802_15_4Table { | ||
| 30 | p_cmdrsp_buffer: MAC_802_15_4_CMD_BUFFER.as_mut_ptr().cast(), | ||
| 31 | p_notack_buffer: MAC_802_15_4_NOTIF_RSP_EVT_BUFFER.as_mut_ptr().cast(), | ||
| 32 | evt_queue: ptr::null_mut(), | ||
| 33 | }); | ||
| 34 | } | ||
| 35 | |||
| 36 | Self { phantom: PhantomData } | 29 | Self { phantom: PhantomData } |
| 37 | } | 30 | } |
| 38 | 31 | ||
| 39 | /// `HW_IPCC_MAC_802_15_4_EvtNot` | 32 | /// `HW_IPCC_MAC_802_15_4_EvtNot` |
| 40 | /// | 33 | /// |
| 41 | /// This function will stall if the previous `EvtBox` has not been dropped | 34 | /// This function will stall if the previous `EvtBox` has not been dropped |
| 42 | pub async fn read(&self) -> EvtBox<Self> { | 35 | pub async fn tl_read(&self) -> EvtBox<Self> { |
| 43 | // Wait for the last event box to be dropped | 36 | // Wait for the last event box to be dropped |
| 44 | poll_fn(|cx| { | 37 | poll_fn(|cx| { |
| 45 | MAC_WAKER.register(cx.waker()); | 38 | MAC_WAKER.register(cx.waker()); |
| @@ -63,9 +56,9 @@ impl Mac { | |||
| 63 | } | 56 | } |
| 64 | 57 | ||
| 65 | /// `HW_IPCC_MAC_802_15_4_CmdEvtNot` | 58 | /// `HW_IPCC_MAC_802_15_4_CmdEvtNot` |
| 66 | pub async fn write_and_get_response(&self, opcode: u16, payload: &[u8]) -> u8 { | 59 | pub async fn tl_write_and_get_response(&self, opcode: u16, payload: &[u8]) -> u8 { |
| 67 | self.write(opcode, payload).await; | 60 | self.tl_write(opcode, payload).await; |
| 68 | Ipcc::flush(channels::cpu1::IPCC_SYSTEM_CMD_RSP_CHANNEL).await; | 61 | Ipcc::flush(channels::cpu1::IPCC_MAC_802_15_4_CMD_RSP_CHANNEL).await; |
| 69 | 62 | ||
| 70 | unsafe { | 63 | unsafe { |
| 71 | let p_event_packet = MAC_802_15_4_CMD_BUFFER.as_ptr() as *const EvtPacket; | 64 | let p_event_packet = MAC_802_15_4_CMD_BUFFER.as_ptr() as *const EvtPacket; |
| @@ -76,19 +69,46 @@ impl Mac { | |||
| 76 | } | 69 | } |
| 77 | 70 | ||
| 78 | /// `TL_MAC_802_15_4_SendCmd` | 71 | /// `TL_MAC_802_15_4_SendCmd` |
| 79 | pub async fn write(&self, opcode: u16, payload: &[u8]) { | 72 | pub async fn tl_write(&self, opcode: u16, payload: &[u8]) { |
| 80 | Ipcc::send(channels::cpu1::IPCC_MAC_802_15_4_CMD_RSP_CHANNEL, || unsafe { | 73 | Ipcc::send(channels::cpu1::IPCC_MAC_802_15_4_CMD_RSP_CHANNEL, || unsafe { |
| 81 | CmdPacket::write_into( | 74 | CmdPacket::write_into( |
| 82 | MAC_802_15_4_CMD_BUFFER.as_mut_ptr(), | 75 | MAC_802_15_4_CMD_BUFFER.as_mut_ptr(), |
| 83 | TlPacketType::OtCmd, | 76 | TlPacketType::MacCmd, |
| 84 | opcode, | 77 | opcode, |
| 85 | payload, | 78 | payload, |
| 86 | ); | 79 | ); |
| 87 | }) | 80 | }) |
| 88 | .await; | 81 | .await; |
| 89 | } | 82 | } |
| 83 | |||
| 84 | pub async fn send_command<T>(&self, cmd: &T) -> Result<(), MacError> | ||
| 85 | where | ||
| 86 | T: MacCommand, | ||
| 87 | { | ||
| 88 | let mut payload = [0u8; MAX_PACKET_SIZE]; | ||
| 89 | cmd.copy_into_slice(&mut payload); | ||
| 90 | |||
| 91 | let response = self | ||
| 92 | .tl_write_and_get_response(T::OPCODE as u16, &payload[..T::SIZE]) | ||
| 93 | .await; | ||
| 94 | |||
| 95 | if response == 0x00 { | ||
| 96 | Ok(()) | ||
| 97 | } else { | ||
| 98 | Err(MacError::from(response)) | ||
| 99 | } | ||
| 100 | } | ||
| 101 | |||
| 102 | pub async fn read(&self) -> Result<MacEvent, ()> { | ||
| 103 | let evt_box = self.tl_read().await; | ||
| 104 | let payload = evt_box.payload(); | ||
| 105 | |||
| 106 | MacEvent::try_from(payload) | ||
| 107 | } | ||
| 90 | } | 108 | } |
| 91 | 109 | ||
| 110 | const MAX_PACKET_SIZE: usize = 255; | ||
| 111 | |||
| 92 | impl evt::MemoryManager for Mac { | 112 | impl evt::MemoryManager for Mac { |
| 93 | /// SAFETY: passing a pointer to something other than a managed event packet is UB | 113 | /// SAFETY: passing a pointer to something other than a managed event packet is UB |
| 94 | unsafe fn drop_event_packet(_: *mut EvtPacket) { | 114 | unsafe fn drop_event_packet(_: *mut EvtPacket) { |
diff --git a/embassy-stm32-wpan/src/sub/mm.rs b/embassy-stm32-wpan/src/sub/mm.rs index 1f2ecac2e..da05ad1dd 100644 --- a/embassy-stm32-wpan/src/sub/mm.rs +++ b/embassy-stm32-wpan/src/sub/mm.rs | |||
| @@ -4,20 +4,21 @@ use core::marker::PhantomData; | |||
| 4 | use core::mem::MaybeUninit; | 4 | use core::mem::MaybeUninit; |
| 5 | use core::task::Poll; | 5 | use core::task::Poll; |
| 6 | 6 | ||
| 7 | use aligned::{Aligned, A4}; | ||
| 7 | use cortex_m::interrupt; | 8 | use cortex_m::interrupt; |
| 8 | use embassy_stm32::ipcc::Ipcc; | 9 | use embassy_stm32::ipcc::Ipcc; |
| 9 | use embassy_sync::waitqueue::AtomicWaker; | 10 | use embassy_sync::waitqueue::AtomicWaker; |
| 10 | 11 | ||
| 11 | use crate::consts::POOL_SIZE; | 12 | use crate::consts::POOL_SIZE; |
| 12 | use crate::evt::EvtPacket; | 13 | use crate::evt::EvtPacket; |
| 13 | use crate::tables::{ | 14 | #[cfg(feature = "ble")] |
| 14 | MemManagerTable, BLE_SPARE_EVT_BUF, EVT_POOL, FREE_BUF_QUEUE, SYS_SPARE_EVT_BUF, TL_MEM_MANAGER_TABLE, | 15 | use crate::tables::BLE_SPARE_EVT_BUF; |
| 15 | }; | 16 | use crate::tables::{MemManagerTable, EVT_POOL, FREE_BUF_QUEUE, SYS_SPARE_EVT_BUF, TL_MEM_MANAGER_TABLE}; |
| 16 | use crate::unsafe_linked_list::LinkedListNode; | 17 | use crate::unsafe_linked_list::LinkedListNode; |
| 17 | use crate::{channels, evt}; | 18 | use crate::{channels, evt}; |
| 18 | 19 | ||
| 19 | static MM_WAKER: AtomicWaker = AtomicWaker::new(); | 20 | static MM_WAKER: AtomicWaker = AtomicWaker::new(); |
| 20 | static mut LOCAL_FREE_BUF_QUEUE: MaybeUninit<LinkedListNode> = MaybeUninit::uninit(); | 21 | static mut LOCAL_FREE_BUF_QUEUE: Aligned<A4, MaybeUninit<LinkedListNode>> = Aligned(MaybeUninit::uninit()); |
| 21 | 22 | ||
| 22 | pub struct MemoryManager { | 23 | pub struct MemoryManager { |
| 23 | phantom: PhantomData<MemoryManager>, | 24 | phantom: PhantomData<MemoryManager>, |
| @@ -30,7 +31,10 @@ impl MemoryManager { | |||
| 30 | LinkedListNode::init_head(LOCAL_FREE_BUF_QUEUE.as_mut_ptr()); | 31 | LinkedListNode::init_head(LOCAL_FREE_BUF_QUEUE.as_mut_ptr()); |
| 31 | 32 | ||
| 32 | TL_MEM_MANAGER_TABLE.as_mut_ptr().write_volatile(MemManagerTable { | 33 | TL_MEM_MANAGER_TABLE.as_mut_ptr().write_volatile(MemManagerTable { |
| 34 | #[cfg(feature = "ble")] | ||
| 33 | spare_ble_buffer: BLE_SPARE_EVT_BUF.as_ptr().cast(), | 35 | spare_ble_buffer: BLE_SPARE_EVT_BUF.as_ptr().cast(), |
| 36 | #[cfg(not(feature = "ble"))] | ||
| 37 | spare_ble_buffer: core::ptr::null(), | ||
| 34 | spare_sys_buffer: SYS_SPARE_EVT_BUF.as_ptr().cast(), | 38 | spare_sys_buffer: SYS_SPARE_EVT_BUF.as_ptr().cast(), |
| 35 | blepool: EVT_POOL.as_ptr().cast(), | 39 | blepool: EVT_POOL.as_ptr().cast(), |
| 36 | blepoolsize: POOL_SIZE as u32, | 40 | blepoolsize: POOL_SIZE as u32, |
diff --git a/embassy-stm32-wpan/src/sub/sys.rs b/embassy-stm32-wpan/src/sub/sys.rs index af652860d..c17fd531d 100644 --- a/embassy-stm32-wpan/src/sub/sys.rs +++ b/embassy-stm32-wpan/src/sub/sys.rs | |||
| @@ -50,7 +50,7 @@ impl Sys { | |||
| 50 | } | 50 | } |
| 51 | 51 | ||
| 52 | /// `HW_IPCC_SYS_CmdEvtNot` | 52 | /// `HW_IPCC_SYS_CmdEvtNot` |
| 53 | pub async fn write_and_get_response(&self, opcode: ShciOpcode, payload: &[u8]) -> SchiCommandStatus { | 53 | pub async fn write_and_get_response(&self, opcode: ShciOpcode, payload: &[u8]) -> Result<SchiCommandStatus, ()> { |
| 54 | self.write(opcode, payload).await; | 54 | self.write(opcode, payload).await; |
| 55 | Ipcc::flush(channels::cpu1::IPCC_SYSTEM_CMD_RSP_CHANNEL).await; | 55 | Ipcc::flush(channels::cpu1::IPCC_SYSTEM_CMD_RSP_CHANNEL).await; |
| 56 | 56 | ||
| @@ -59,17 +59,36 @@ impl Sys { | |||
| 59 | let p_command_event = &((*p_event_packet).evt_serial.evt.payload) as *const _ as *const CcEvt; | 59 | let p_command_event = &((*p_event_packet).evt_serial.evt.payload) as *const _ as *const CcEvt; |
| 60 | let p_payload = &((*p_command_event).payload) as *const u8; | 60 | let p_payload = &((*p_command_event).payload) as *const u8; |
| 61 | 61 | ||
| 62 | ptr::read_volatile(p_payload).try_into().unwrap() | 62 | ptr::read_volatile(p_payload).try_into() |
| 63 | } | 63 | } |
| 64 | } | 64 | } |
| 65 | 65 | ||
| 66 | #[cfg(feature = "mac")] | 66 | #[cfg(feature = "mac")] |
| 67 | pub async fn shci_c2_mac_802_15_4_init(&self) -> SchiCommandStatus { | 67 | pub async fn shci_c2_mac_802_15_4_init(&self) -> Result<SchiCommandStatus, ()> { |
| 68 | use crate::tables::{ | ||
| 69 | Mac802_15_4Table, TracesTable, MAC_802_15_4_CMD_BUFFER, MAC_802_15_4_NOTIF_RSP_EVT_BUFFER, | ||
| 70 | TL_MAC_802_15_4_TABLE, TL_TRACES_TABLE, TRACES_EVT_QUEUE, | ||
| 71 | }; | ||
| 72 | |||
| 73 | unsafe { | ||
| 74 | LinkedListNode::init_head(TRACES_EVT_QUEUE.as_mut_ptr() as *mut _); | ||
| 75 | |||
| 76 | TL_TRACES_TABLE.as_mut_ptr().write_volatile(TracesTable { | ||
| 77 | traces_queue: TRACES_EVT_QUEUE.as_ptr() as *const _, | ||
| 78 | }); | ||
| 79 | |||
| 80 | TL_MAC_802_15_4_TABLE.as_mut_ptr().write_volatile(Mac802_15_4Table { | ||
| 81 | p_cmdrsp_buffer: MAC_802_15_4_CMD_BUFFER.as_mut_ptr().cast(), | ||
| 82 | p_notack_buffer: MAC_802_15_4_NOTIF_RSP_EVT_BUFFER.as_mut_ptr().cast(), | ||
| 83 | evt_queue: core::ptr::null_mut(), | ||
| 84 | }); | ||
| 85 | }; | ||
| 86 | |||
| 68 | self.write_and_get_response(ShciOpcode::Mac802_15_4Init, &[]).await | 87 | self.write_and_get_response(ShciOpcode::Mac802_15_4Init, &[]).await |
| 69 | } | 88 | } |
| 70 | 89 | ||
| 71 | #[cfg(feature = "ble")] | 90 | #[cfg(feature = "ble")] |
| 72 | pub async fn shci_c2_ble_init(&self, param: ShciBleInitCmdParam) -> SchiCommandStatus { | 91 | pub async fn shci_c2_ble_init(&self, param: ShciBleInitCmdParam) -> Result<SchiCommandStatus, ()> { |
| 73 | self.write_and_get_response(ShciOpcode::BleInit, param.payload()).await | 92 | self.write_and_get_response(ShciOpcode::BleInit, param.payload()).await |
| 74 | } | 93 | } |
| 75 | 94 | ||
diff --git a/embassy-stm32-wpan/src/tables.rs b/embassy-stm32-wpan/src/tables.rs index 1b5dcdf2e..f2c250527 100644 --- a/embassy-stm32-wpan/src/tables.rs +++ b/embassy-stm32-wpan/src/tables.rs | |||
| @@ -4,6 +4,8 @@ use aligned::{Aligned, A4}; | |||
| 4 | use bit_field::BitField; | 4 | use bit_field::BitField; |
| 5 | 5 | ||
| 6 | use crate::cmd::{AclDataPacket, CmdPacket}; | 6 | use crate::cmd::{AclDataPacket, CmdPacket}; |
| 7 | #[cfg(feature = "mac")] | ||
| 8 | use crate::consts::C_SIZE_CMD_STRING; | ||
| 7 | use crate::consts::{POOL_SIZE, TL_CS_EVT_SIZE, TL_EVT_HEADER_SIZE, TL_PACKET_HEADER_SIZE}; | 9 | use crate::consts::{POOL_SIZE, TL_CS_EVT_SIZE, TL_EVT_HEADER_SIZE, TL_PACKET_HEADER_SIZE}; |
| 8 | use crate::unsafe_linked_list::LinkedListNode; | 10 | use crate::unsafe_linked_list::LinkedListNode; |
| 9 | 11 | ||
| @@ -80,7 +82,7 @@ impl WirelessFwInfoTable { | |||
| 80 | } | 82 | } |
| 81 | 83 | ||
| 82 | #[derive(Debug, Clone)] | 84 | #[derive(Debug, Clone)] |
| 83 | #[repr(C, align(4))] | 85 | #[repr(C)] |
| 84 | pub struct DeviceInfoTable { | 86 | pub struct DeviceInfoTable { |
| 85 | pub safe_boot_info_table: SafeBootInfoTable, | 87 | pub safe_boot_info_table: SafeBootInfoTable, |
| 86 | pub rss_info_table: RssInfoTable, | 88 | pub rss_info_table: RssInfoTable, |
| @@ -88,7 +90,7 @@ pub struct DeviceInfoTable { | |||
| 88 | } | 90 | } |
| 89 | 91 | ||
| 90 | #[derive(Debug)] | 92 | #[derive(Debug)] |
| 91 | #[repr(C, align(4))] | 93 | #[repr(C)] |
| 92 | pub struct BleTable { | 94 | pub struct BleTable { |
| 93 | pub pcmd_buffer: *mut CmdPacket, | 95 | pub pcmd_buffer: *mut CmdPacket, |
| 94 | pub pcs_buffer: *const u8, | 96 | pub pcs_buffer: *const u8, |
| @@ -97,16 +99,15 @@ pub struct BleTable { | |||
| 97 | } | 99 | } |
| 98 | 100 | ||
| 99 | #[derive(Debug)] | 101 | #[derive(Debug)] |
| 100 | #[repr(C, align(4))] | 102 | #[repr(C)] |
| 101 | pub struct ThreadTable { | 103 | pub struct ThreadTable { |
| 102 | pub nostack_buffer: *const u8, | 104 | pub nostack_buffer: *const u8, |
| 103 | pub clicmdrsp_buffer: *const u8, | 105 | pub clicmdrsp_buffer: *const u8, |
| 104 | pub otcmdrsp_buffer: *const u8, | 106 | pub otcmdrsp_buffer: *const u8, |
| 105 | } | 107 | } |
| 106 | 108 | ||
| 107 | // TODO: use later | ||
| 108 | #[derive(Debug)] | 109 | #[derive(Debug)] |
| 109 | #[repr(C, align(4))] | 110 | #[repr(C)] |
| 110 | pub struct LldTestsTable { | 111 | pub struct LldTestsTable { |
| 111 | pub clicmdrsp_buffer: *const u8, | 112 | pub clicmdrsp_buffer: *const u8, |
| 112 | pub m0cmd_buffer: *const u8, | 113 | pub m0cmd_buffer: *const u8, |
| @@ -114,7 +115,7 @@ pub struct LldTestsTable { | |||
| 114 | 115 | ||
| 115 | // TODO: use later | 116 | // TODO: use later |
| 116 | #[derive(Debug)] | 117 | #[derive(Debug)] |
| 117 | #[repr(C, align(4))] | 118 | #[repr(C)] |
| 118 | pub struct BleLldTable { | 119 | pub struct BleLldTable { |
| 119 | pub cmdrsp_buffer: *const u8, | 120 | pub cmdrsp_buffer: *const u8, |
| 120 | pub m0cmd_buffer: *const u8, | 121 | pub m0cmd_buffer: *const u8, |
| @@ -122,7 +123,7 @@ pub struct BleLldTable { | |||
| 122 | 123 | ||
| 123 | // TODO: use later | 124 | // TODO: use later |
| 124 | #[derive(Debug)] | 125 | #[derive(Debug)] |
| 125 | #[repr(C, align(4))] | 126 | #[repr(C)] |
| 126 | pub struct ZigbeeTable { | 127 | pub struct ZigbeeTable { |
| 127 | pub notif_m0_to_m4_buffer: *const u8, | 128 | pub notif_m0_to_m4_buffer: *const u8, |
| 128 | pub appli_cmd_m4_to_m0_bufer: *const u8, | 129 | pub appli_cmd_m4_to_m0_bufer: *const u8, |
| @@ -130,14 +131,14 @@ pub struct ZigbeeTable { | |||
| 130 | } | 131 | } |
| 131 | 132 | ||
| 132 | #[derive(Debug)] | 133 | #[derive(Debug)] |
| 133 | #[repr(C, align(4))] | 134 | #[repr(C)] |
| 134 | pub struct SysTable { | 135 | pub struct SysTable { |
| 135 | pub pcmd_buffer: *mut CmdPacket, | 136 | pub pcmd_buffer: *mut CmdPacket, |
| 136 | pub sys_queue: *const LinkedListNode, | 137 | pub sys_queue: *const LinkedListNode, |
| 137 | } | 138 | } |
| 138 | 139 | ||
| 139 | #[derive(Debug)] | 140 | #[derive(Debug)] |
| 140 | #[repr(C, align(4))] | 141 | #[repr(C)] |
| 141 | pub struct MemManagerTable { | 142 | pub struct MemManagerTable { |
| 142 | pub spare_ble_buffer: *const u8, | 143 | pub spare_ble_buffer: *const u8, |
| 143 | pub spare_sys_buffer: *const u8, | 144 | pub spare_sys_buffer: *const u8, |
| @@ -152,13 +153,13 @@ pub struct MemManagerTable { | |||
| 152 | } | 153 | } |
| 153 | 154 | ||
| 154 | #[derive(Debug)] | 155 | #[derive(Debug)] |
| 155 | #[repr(C, align(4))] | 156 | #[repr(C)] |
| 156 | pub struct TracesTable { | 157 | pub struct TracesTable { |
| 157 | pub traces_queue: *const u8, | 158 | pub traces_queue: *const u8, |
| 158 | } | 159 | } |
| 159 | 160 | ||
| 160 | #[derive(Debug)] | 161 | #[derive(Debug)] |
| 161 | #[repr(C, align(4))] | 162 | #[repr(C)] |
| 162 | pub struct Mac802_15_4Table { | 163 | pub struct Mac802_15_4Table { |
| 163 | pub p_cmdrsp_buffer: *const u8, | 164 | pub p_cmdrsp_buffer: *const u8, |
| 164 | pub p_notack_buffer: *const u8, | 165 | pub p_notack_buffer: *const u8, |
| @@ -176,6 +177,9 @@ pub struct RefTable { | |||
| 176 | pub mem_manager_table: *const MemManagerTable, | 177 | pub mem_manager_table: *const MemManagerTable, |
| 177 | pub traces_table: *const TracesTable, | 178 | pub traces_table: *const TracesTable, |
| 178 | pub mac_802_15_4_table: *const Mac802_15_4Table, | 179 | pub mac_802_15_4_table: *const Mac802_15_4Table, |
| 180 | pub zigbee_table: *const ZigbeeTable, | ||
| 181 | pub lld_tests_table: *const LldTestsTable, | ||
| 182 | pub ble_lld_table: *const BleLldTable, | ||
| 179 | } | 183 | } |
| 180 | 184 | ||
| 181 | // --------------------- ref table --------------------- | 185 | // --------------------- ref table --------------------- |
| @@ -183,57 +187,57 @@ pub struct RefTable { | |||
| 183 | pub static mut TL_REF_TABLE: MaybeUninit<RefTable> = MaybeUninit::uninit(); | 187 | pub static mut TL_REF_TABLE: MaybeUninit<RefTable> = MaybeUninit::uninit(); |
| 184 | 188 | ||
| 185 | #[link_section = "MB_MEM1"] | 189 | #[link_section = "MB_MEM1"] |
| 186 | pub static mut TL_DEVICE_INFO_TABLE: MaybeUninit<DeviceInfoTable> = MaybeUninit::uninit(); | 190 | pub static mut TL_DEVICE_INFO_TABLE: Aligned<A4, MaybeUninit<DeviceInfoTable>> = Aligned(MaybeUninit::uninit()); |
| 187 | 191 | ||
| 188 | #[link_section = "MB_MEM1"] | 192 | #[link_section = "MB_MEM1"] |
| 189 | pub static mut TL_BLE_TABLE: MaybeUninit<BleTable> = MaybeUninit::uninit(); | 193 | pub static mut TL_BLE_TABLE: Aligned<A4, MaybeUninit<BleTable>> = Aligned(MaybeUninit::uninit()); |
| 190 | 194 | ||
| 191 | #[link_section = "MB_MEM1"] | 195 | #[link_section = "MB_MEM1"] |
| 192 | pub static mut TL_THREAD_TABLE: MaybeUninit<ThreadTable> = MaybeUninit::uninit(); | 196 | pub static mut TL_THREAD_TABLE: Aligned<A4, MaybeUninit<ThreadTable>> = Aligned(MaybeUninit::uninit()); |
| 193 | 197 | ||
| 194 | // #[link_section = "MB_MEM1"] | 198 | #[link_section = "MB_MEM1"] |
| 195 | // pub static mut TL_LLD_TESTS_TABLE: MaybeUninit<LldTestTable> = MaybeUninit::uninit(); | 199 | pub static mut TL_LLD_TESTS_TABLE: Aligned<A4, MaybeUninit<LldTestsTable>> = Aligned(MaybeUninit::uninit()); |
| 196 | 200 | ||
| 197 | // #[link_section = "MB_MEM1"] | 201 | #[link_section = "MB_MEM1"] |
| 198 | // pub static mut TL_BLE_LLD_TABLE: MaybeUninit<BleLldTable> = MaybeUninit::uninit(); | 202 | pub static mut TL_BLE_LLD_TABLE: Aligned<A4, MaybeUninit<BleLldTable>> = Aligned(MaybeUninit::uninit()); |
| 199 | 203 | ||
| 200 | #[link_section = "MB_MEM1"] | 204 | #[link_section = "MB_MEM1"] |
| 201 | pub static mut TL_SYS_TABLE: MaybeUninit<SysTable> = MaybeUninit::uninit(); | 205 | pub static mut TL_SYS_TABLE: Aligned<A4, MaybeUninit<SysTable>> = Aligned(MaybeUninit::uninit()); |
| 202 | 206 | ||
| 203 | #[link_section = "MB_MEM1"] | 207 | #[link_section = "MB_MEM1"] |
| 204 | pub static mut TL_MEM_MANAGER_TABLE: MaybeUninit<MemManagerTable> = MaybeUninit::uninit(); | 208 | pub static mut TL_MEM_MANAGER_TABLE: Aligned<A4, MaybeUninit<MemManagerTable>> = Aligned(MaybeUninit::uninit()); |
| 205 | 209 | ||
| 206 | #[link_section = "MB_MEM1"] | 210 | #[link_section = "MB_MEM1"] |
| 207 | pub static mut TL_TRACES_TABLE: MaybeUninit<TracesTable> = MaybeUninit::uninit(); | 211 | pub static mut TL_TRACES_TABLE: Aligned<A4, MaybeUninit<TracesTable>> = Aligned(MaybeUninit::uninit()); |
| 208 | 212 | ||
| 209 | #[link_section = "MB_MEM1"] | 213 | #[link_section = "MB_MEM1"] |
| 210 | pub static mut TL_MAC_802_15_4_TABLE: MaybeUninit<Mac802_15_4Table> = MaybeUninit::uninit(); | 214 | pub static mut TL_MAC_802_15_4_TABLE: Aligned<A4, MaybeUninit<Mac802_15_4Table>> = Aligned(MaybeUninit::uninit()); |
| 211 | 215 | ||
| 212 | // #[link_section = "MB_MEM1"] | 216 | #[link_section = "MB_MEM1"] |
| 213 | // pub static mut TL_ZIGBEE_TABLE: MaybeUninit<ZigbeeTable> = MaybeUninit::uninit(); | 217 | pub static mut TL_ZIGBEE_TABLE: Aligned<A4, MaybeUninit<ZigbeeTable>> = Aligned(MaybeUninit::uninit()); |
| 214 | 218 | ||
| 215 | // --------------------- tables --------------------- | 219 | // --------------------- tables --------------------- |
| 216 | #[link_section = "MB_MEM1"] | 220 | #[link_section = "MB_MEM1"] |
| 217 | pub static mut FREE_BUF_QUEUE: MaybeUninit<LinkedListNode> = MaybeUninit::uninit(); | 221 | pub static mut FREE_BUF_QUEUE: Aligned<A4, MaybeUninit<LinkedListNode>> = Aligned(MaybeUninit::uninit()); |
| 218 | 222 | ||
| 219 | #[allow(dead_code)] | 223 | #[allow(dead_code)] |
| 220 | #[link_section = "MB_MEM1"] | 224 | #[link_section = "MB_MEM1"] |
| 221 | pub static mut TRACES_EVT_QUEUE: MaybeUninit<LinkedListNode> = MaybeUninit::uninit(); | 225 | pub static mut TRACES_EVT_QUEUE: Aligned<A4, MaybeUninit<LinkedListNode>> = Aligned(MaybeUninit::uninit()); |
| 222 | 226 | ||
| 223 | #[link_section = "MB_MEM2"] | 227 | #[link_section = "MB_MEM2"] |
| 224 | pub static mut CS_BUFFER: MaybeUninit<Aligned<A4, [u8; TL_PACKET_HEADER_SIZE + TL_EVT_HEADER_SIZE + TL_CS_EVT_SIZE]>> = | 228 | pub static mut CS_BUFFER: Aligned<A4, MaybeUninit<[u8; TL_PACKET_HEADER_SIZE + TL_EVT_HEADER_SIZE + TL_CS_EVT_SIZE]>> = |
| 225 | MaybeUninit::uninit(); | 229 | Aligned(MaybeUninit::uninit()); |
| 226 | 230 | ||
| 227 | #[link_section = "MB_MEM2"] | 231 | #[link_section = "MB_MEM2"] |
| 228 | pub static mut EVT_QUEUE: MaybeUninit<LinkedListNode> = MaybeUninit::uninit(); | 232 | pub static mut EVT_QUEUE: Aligned<A4, MaybeUninit<LinkedListNode>> = Aligned(MaybeUninit::uninit()); |
| 229 | 233 | ||
| 230 | #[link_section = "MB_MEM2"] | 234 | #[link_section = "MB_MEM2"] |
| 231 | pub static mut SYSTEM_EVT_QUEUE: MaybeUninit<LinkedListNode> = MaybeUninit::uninit(); | 235 | pub static mut SYSTEM_EVT_QUEUE: Aligned<A4, MaybeUninit<LinkedListNode>> = Aligned(MaybeUninit::uninit()); |
| 232 | 236 | ||
| 233 | // --------------------- app tables --------------------- | 237 | // --------------------- app tables --------------------- |
| 234 | #[cfg(feature = "mac")] | 238 | #[cfg(feature = "mac")] |
| 235 | #[link_section = "MB_MEM2"] | 239 | #[link_section = "MB_MEM2"] |
| 236 | pub static mut MAC_802_15_4_CMD_BUFFER: MaybeUninit<CmdPacket> = MaybeUninit::uninit(); | 240 | pub static mut MAC_802_15_4_CMD_BUFFER: Aligned<A4, MaybeUninit<CmdPacket>> = Aligned(MaybeUninit::uninit()); |
| 237 | 241 | ||
| 238 | #[cfg(feature = "mac")] | 242 | #[cfg(feature = "mac")] |
| 239 | #[link_section = "MB_MEM2"] | 243 | #[link_section = "MB_MEM2"] |
| @@ -242,23 +246,31 @@ pub static mut MAC_802_15_4_NOTIF_RSP_EVT_BUFFER: MaybeUninit< | |||
| 242 | > = MaybeUninit::uninit(); | 246 | > = MaybeUninit::uninit(); |
| 243 | 247 | ||
| 244 | #[link_section = "MB_MEM2"] | 248 | #[link_section = "MB_MEM2"] |
| 245 | pub static mut EVT_POOL: MaybeUninit<Aligned<A4, [u8; POOL_SIZE]>> = MaybeUninit::uninit(); | 249 | pub static mut EVT_POOL: Aligned<A4, MaybeUninit<[u8; POOL_SIZE]>> = Aligned(MaybeUninit::uninit()); |
| 250 | |||
| 251 | #[link_section = "MB_MEM2"] | ||
| 252 | pub static mut SYS_CMD_BUF: Aligned<A4, MaybeUninit<CmdPacket>> = Aligned(MaybeUninit::uninit()); | ||
| 246 | 253 | ||
| 247 | #[link_section = "MB_MEM2"] | 254 | #[link_section = "MB_MEM2"] |
| 248 | pub static mut SYS_CMD_BUF: MaybeUninit<CmdPacket> = MaybeUninit::uninit(); | 255 | pub static mut SYS_SPARE_EVT_BUF: Aligned<A4, MaybeUninit<[u8; TL_PACKET_HEADER_SIZE + TL_EVT_HEADER_SIZE + 255]>> = |
| 256 | Aligned(MaybeUninit::uninit()); | ||
| 249 | 257 | ||
| 258 | #[cfg(feature = "mac")] | ||
| 250 | #[link_section = "MB_MEM2"] | 259 | #[link_section = "MB_MEM2"] |
| 251 | pub static mut SYS_SPARE_EVT_BUF: MaybeUninit<Aligned<A4, [u8; TL_PACKET_HEADER_SIZE + TL_EVT_HEADER_SIZE + 255]>> = | 260 | pub static mut MAC_802_15_4_CNFINDNOT: Aligned<A4, MaybeUninit<[u8; C_SIZE_CMD_STRING]>> = |
| 252 | MaybeUninit::uninit(); | 261 | Aligned(MaybeUninit::uninit()); |
| 253 | 262 | ||
| 263 | #[cfg(feature = "ble")] | ||
| 254 | #[link_section = "MB_MEM1"] | 264 | #[link_section = "MB_MEM1"] |
| 255 | pub static mut BLE_CMD_BUFFER: MaybeUninit<CmdPacket> = MaybeUninit::uninit(); | 265 | pub static mut BLE_CMD_BUFFER: Aligned<A4, MaybeUninit<CmdPacket>> = Aligned(MaybeUninit::uninit()); |
| 256 | 266 | ||
| 267 | #[cfg(feature = "ble")] | ||
| 257 | #[link_section = "MB_MEM2"] | 268 | #[link_section = "MB_MEM2"] |
| 258 | pub static mut BLE_SPARE_EVT_BUF: MaybeUninit<Aligned<A4, [u8; TL_PACKET_HEADER_SIZE + TL_EVT_HEADER_SIZE + 255]>> = | 269 | pub static mut BLE_SPARE_EVT_BUF: Aligned<A4, MaybeUninit<[u8; TL_PACKET_HEADER_SIZE + TL_EVT_HEADER_SIZE + 255]>> = |
| 259 | MaybeUninit::uninit(); | 270 | Aligned(MaybeUninit::uninit()); |
| 260 | 271 | ||
| 272 | #[cfg(feature = "ble")] | ||
| 261 | #[link_section = "MB_MEM2"] | 273 | #[link_section = "MB_MEM2"] |
| 262 | // fuck these "magic" numbers from ST ---v---v | 274 | // fuck these "magic" numbers from ST ---v---v |
| 263 | pub static mut HCI_ACL_DATA_BUFFER: MaybeUninit<Aligned<A4, [u8; TL_PACKET_HEADER_SIZE + 5 + 251]>> = | 275 | pub static mut HCI_ACL_DATA_BUFFER: Aligned<A4, MaybeUninit<[u8; TL_PACKET_HEADER_SIZE + 5 + 251]>> = |
| 264 | MaybeUninit::uninit(); | 276 | Aligned(MaybeUninit::uninit()); |
diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml index b3fe9c1f5..ec934e8be 100644 --- a/embassy-stm32/Cargo.toml +++ b/embassy-stm32/Cargo.toml | |||
| @@ -32,7 +32,7 @@ flavors = [ | |||
| 32 | 32 | ||
| 33 | [dependencies] | 33 | [dependencies] |
| 34 | embassy-sync = { version = "0.2.0", path = "../embassy-sync" } | 34 | embassy-sync = { version = "0.2.0", path = "../embassy-sync" } |
| 35 | embassy-time = { version = "0.1.0", path = "../embassy-time", optional = true } | 35 | embassy-time = { version = "0.1.2", path = "../embassy-time", optional = true } |
| 36 | embassy-futures = { version = "0.1.0", path = "../embassy-futures" } | 36 | embassy-futures = { version = "0.1.0", path = "../embassy-futures" } |
| 37 | embassy-hal-common = {version = "0.1.0", path = "../embassy-hal-common", features = ["cortex-m", "prio-bits-4"] } | 37 | embassy-hal-common = {version = "0.1.0", path = "../embassy-hal-common", features = ["cortex-m", "prio-bits-4"] } |
| 38 | embassy-embedded-hal = {version = "0.1.0", path = "../embassy-embedded-hal" } | 38 | embassy-embedded-hal = {version = "0.1.0", path = "../embassy-embedded-hal" } |
| @@ -40,9 +40,9 @@ embassy-net-driver = { version = "0.1.0", path = "../embassy-net-driver" } | |||
| 40 | embassy-usb-driver = {version = "0.1.0", path = "../embassy-usb-driver", optional = true } | 40 | embassy-usb-driver = {version = "0.1.0", path = "../embassy-usb-driver", optional = true } |
| 41 | 41 | ||
| 42 | embedded-hal-02 = { package = "embedded-hal", version = "0.2.6", features = ["unproven"] } | 42 | embedded-hal-02 = { package = "embedded-hal", version = "0.2.6", features = ["unproven"] } |
| 43 | embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-alpha.10", optional = true} | 43 | embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-alpha.11", optional = true} |
| 44 | embedded-hal-async = { version = "=0.2.0-alpha.1", optional = true} | 44 | embedded-hal-async = { version = "=0.2.0-alpha.2", optional = true} |
| 45 | embedded-hal-nb = { version = "=1.0.0-alpha.2", optional = true} | 45 | embedded-hal-nb = { version = "=1.0.0-alpha.3", optional = true} |
| 46 | 46 | ||
| 47 | embedded-storage = "0.3.0" | 47 | embedded-storage = "0.3.0" |
| 48 | embedded-storage-async = { version = "0.4.0", optional = true } | 48 | embedded-storage-async = { version = "0.4.0", optional = true } |
diff --git a/embassy-stm32/build.rs b/embassy-stm32/build.rs index fa66da1f6..995ad1443 100644 --- a/embassy-stm32/build.rs +++ b/embassy-stm32/build.rs | |||
| @@ -348,9 +348,7 @@ fn main() { | |||
| 348 | g.extend(quote! { | 348 | g.extend(quote! { |
| 349 | impl crate::rcc::sealed::RccPeripheral for peripherals::#pname { | 349 | impl crate::rcc::sealed::RccPeripheral for peripherals::#pname { |
| 350 | fn frequency() -> crate::time::Hertz { | 350 | fn frequency() -> crate::time::Hertz { |
| 351 | critical_section::with(|_| unsafe { | 351 | unsafe { crate::rcc::get_freqs().#clk } |
| 352 | crate::rcc::get_freqs().#clk | ||
| 353 | }) | ||
| 354 | } | 352 | } |
| 355 | fn enable() { | 353 | fn enable() { |
| 356 | critical_section::with(|_| { | 354 | critical_section::with(|_| { |
diff --git a/embassy-stm32/src/can/bxcan.rs b/embassy-stm32/src/can/bxcan.rs index 73861776a..5a0153464 100644 --- a/embassy-stm32/src/can/bxcan.rs +++ b/embassy-stm32/src/can/bxcan.rs | |||
| @@ -1,3 +1,4 @@ | |||
| 1 | use core::cell::{RefCell, RefMut}; | ||
| 1 | use core::future::poll_fn; | 2 | use core::future::poll_fn; |
| 2 | use core::marker::PhantomData; | 3 | use core::marker::PhantomData; |
| 3 | use core::ops::{Deref, DerefMut}; | 4 | use core::ops::{Deref, DerefMut}; |
| @@ -72,7 +73,7 @@ impl<T: Instance> interrupt::typelevel::Handler<T::SCEInterrupt> for SceInterrup | |||
| 72 | } | 73 | } |
| 73 | 74 | ||
| 74 | pub struct Can<'d, T: Instance> { | 75 | pub struct Can<'d, T: Instance> { |
| 75 | can: bxcan::Can<BxcanInstance<'d, T>>, | 76 | pub can: RefCell<bxcan::Can<BxcanInstance<'d, T>>>, |
| 76 | } | 77 | } |
| 77 | 78 | ||
| 78 | #[derive(Debug)] | 79 | #[derive(Debug)] |
| @@ -147,19 +148,24 @@ impl<'d, T: Instance> Can<'d, T> { | |||
| 147 | tx.set_as_af(tx.af_num(), AFType::OutputPushPull); | 148 | tx.set_as_af(tx.af_num(), AFType::OutputPushPull); |
| 148 | 149 | ||
| 149 | let can = bxcan::Can::builder(BxcanInstance(peri)).leave_disabled(); | 150 | let can = bxcan::Can::builder(BxcanInstance(peri)).leave_disabled(); |
| 150 | Self { can } | 151 | let can_ref_cell = RefCell::new(can); |
| 152 | Self { can: can_ref_cell } | ||
| 151 | } | 153 | } |
| 152 | 154 | ||
| 153 | pub fn set_bitrate(&mut self, bitrate: u32) { | 155 | pub fn set_bitrate(&mut self, bitrate: u32) { |
| 154 | let bit_timing = Self::calc_bxcan_timings(T::frequency(), bitrate).unwrap(); | 156 | let bit_timing = Self::calc_bxcan_timings(T::frequency(), bitrate).unwrap(); |
| 155 | self.can.modify_config().set_bit_timing(bit_timing).leave_disabled(); | 157 | self.can |
| 158 | .borrow_mut() | ||
| 159 | .modify_config() | ||
| 160 | .set_bit_timing(bit_timing) | ||
| 161 | .leave_disabled(); | ||
| 156 | } | 162 | } |
| 157 | 163 | ||
| 158 | /// Queues the message to be sent but exerts backpressure | 164 | /// Queues the message to be sent but exerts backpressure |
| 159 | pub async fn write(&mut self, frame: &Frame) -> bxcan::TransmitStatus { | 165 | pub async fn write(&mut self, frame: &Frame) -> bxcan::TransmitStatus { |
| 160 | poll_fn(|cx| { | 166 | poll_fn(|cx| { |
| 161 | T::state().tx_waker.register(cx.waker()); | 167 | T::state().tx_waker.register(cx.waker()); |
| 162 | if let Ok(status) = self.can.transmit(frame) { | 168 | if let Ok(status) = self.can.borrow_mut().transmit(frame) { |
| 163 | return Poll::Ready(status); | 169 | return Poll::Ready(status); |
| 164 | } | 170 | } |
| 165 | 171 | ||
| @@ -341,6 +347,79 @@ impl<'d, T: Instance> Can<'d, T> { | |||
| 341 | // Pack into BTR register values | 347 | // Pack into BTR register values |
| 342 | Some((sjw - 1) << 24 | (bs1 as u32 - 1) << 16 | (bs2 as u32 - 1) << 20 | (prescaler as u32 - 1)) | 348 | Some((sjw - 1) << 24 | (bs1 as u32 - 1) << 16 | (bs2 as u32 - 1) << 20 | (prescaler as u32 - 1)) |
| 343 | } | 349 | } |
| 350 | |||
| 351 | pub fn split<'c>(&'c self) -> (CanTx<'c, 'd, T>, CanRx<'c, 'd, T>) { | ||
| 352 | (CanTx { can: &self.can }, CanRx { can: &self.can }) | ||
| 353 | } | ||
| 354 | |||
| 355 | pub fn as_mut(&self) -> RefMut<'_, bxcan::Can<BxcanInstance<'d, T>>> { | ||
| 356 | self.can.borrow_mut() | ||
| 357 | } | ||
| 358 | } | ||
| 359 | |||
| 360 | pub struct CanTx<'c, 'd, T: Instance> { | ||
| 361 | can: &'c RefCell<bxcan::Can<BxcanInstance<'d, T>>>, | ||
| 362 | } | ||
| 363 | |||
| 364 | impl<'c, 'd, T: Instance> CanTx<'c, 'd, T> { | ||
| 365 | pub async fn write(&mut self, frame: &Frame) -> bxcan::TransmitStatus { | ||
| 366 | poll_fn(|cx| { | ||
| 367 | T::state().tx_waker.register(cx.waker()); | ||
| 368 | if let Ok(status) = self.can.borrow_mut().transmit(frame) { | ||
| 369 | return Poll::Ready(status); | ||
| 370 | } | ||
| 371 | |||
| 372 | Poll::Pending | ||
| 373 | }) | ||
| 374 | .await | ||
| 375 | } | ||
| 376 | |||
| 377 | pub async fn flush(&self, mb: bxcan::Mailbox) { | ||
| 378 | poll_fn(|cx| { | ||
| 379 | T::state().tx_waker.register(cx.waker()); | ||
| 380 | if T::regs().tsr().read().tme(mb.index()) { | ||
| 381 | return Poll::Ready(()); | ||
| 382 | } | ||
| 383 | |||
| 384 | Poll::Pending | ||
| 385 | }) | ||
| 386 | .await; | ||
| 387 | } | ||
| 388 | } | ||
| 389 | |||
| 390 | #[allow(dead_code)] | ||
| 391 | pub struct CanRx<'c, 'd, T: Instance> { | ||
| 392 | can: &'c RefCell<bxcan::Can<BxcanInstance<'d, T>>>, | ||
| 393 | } | ||
| 394 | |||
| 395 | impl<'c, 'd, T: Instance> CanRx<'c, 'd, T> { | ||
| 396 | pub async fn read(&mut self) -> Result<(u16, bxcan::Frame), BusError> { | ||
| 397 | poll_fn(|cx| { | ||
| 398 | T::state().err_waker.register(cx.waker()); | ||
| 399 | if let Poll::Ready((time, frame)) = T::state().rx_queue.recv().poll_unpin(cx) { | ||
| 400 | return Poll::Ready(Ok((time, frame))); | ||
| 401 | } else if let Some(err) = self.curr_error() { | ||
| 402 | return Poll::Ready(Err(err)); | ||
| 403 | } | ||
| 404 | |||
| 405 | Poll::Pending | ||
| 406 | }) | ||
| 407 | .await | ||
| 408 | } | ||
| 409 | |||
| 410 | fn curr_error(&self) -> Option<BusError> { | ||
| 411 | let err = { T::regs().esr().read() }; | ||
| 412 | if err.boff() { | ||
| 413 | return Some(BusError::BusOff); | ||
| 414 | } else if err.epvf() { | ||
| 415 | return Some(BusError::BusPassive); | ||
| 416 | } else if err.ewgf() { | ||
| 417 | return Some(BusError::BusWarning); | ||
| 418 | } else if let Some(err) = err.lec().into_bus_err() { | ||
| 419 | return Some(err); | ||
| 420 | } | ||
| 421 | None | ||
| 422 | } | ||
| 344 | } | 423 | } |
| 345 | 424 | ||
| 346 | enum RxFifo { | 425 | enum RxFifo { |
| @@ -358,7 +437,7 @@ impl<'d, T: Instance> Drop for Can<'d, T> { | |||
| 358 | } | 437 | } |
| 359 | 438 | ||
| 360 | impl<'d, T: Instance> Deref for Can<'d, T> { | 439 | impl<'d, T: Instance> Deref for Can<'d, T> { |
| 361 | type Target = bxcan::Can<BxcanInstance<'d, T>>; | 440 | type Target = RefCell<bxcan::Can<BxcanInstance<'d, T>>>; |
| 362 | 441 | ||
| 363 | fn deref(&self) -> &Self::Target { | 442 | fn deref(&self) -> &Self::Target { |
| 364 | &self.can | 443 | &self.can |
diff --git a/embassy-stm32/src/dac/mod.rs b/embassy-stm32/src/dac/mod.rs index 1dc13949d..31a2d8863 100644 --- a/embassy-stm32/src/dac/mod.rs +++ b/embassy-stm32/src/dac/mod.rs | |||
| @@ -264,7 +264,7 @@ impl<'d, T: Instance, Tx> DacCh1<'d, T, Tx> { | |||
| 264 | }); | 264 | }); |
| 265 | 265 | ||
| 266 | let tx_request = self.dma.request(); | 266 | let tx_request = self.dma.request(); |
| 267 | let dma_channel = &self.dma; | 267 | let dma_channel = &mut self.dma; |
| 268 | 268 | ||
| 269 | let tx_options = crate::dma::TransferOptions { | 269 | let tx_options = crate::dma::TransferOptions { |
| 270 | circular, | 270 | circular, |
| @@ -376,7 +376,7 @@ impl<'d, T: Instance, Tx> DacCh2<'d, T, Tx> { | |||
| 376 | }); | 376 | }); |
| 377 | 377 | ||
| 378 | let tx_request = self.dma.request(); | 378 | let tx_request = self.dma.request(); |
| 379 | let dma_channel = &self.dma; | 379 | let dma_channel = &mut self.dma; |
| 380 | 380 | ||
| 381 | let tx_options = crate::dma::TransferOptions { | 381 | let tx_options = crate::dma::TransferOptions { |
| 382 | circular, | 382 | circular, |
diff --git a/embassy-stm32/src/dma/dma.rs b/embassy-stm32/src/dma/dma.rs index 8abe541d3..58d438af8 100644 --- a/embassy-stm32/src/dma/dma.rs +++ b/embassy-stm32/src/dma/dma.rs | |||
| @@ -1,10 +1,9 @@ | |||
| 1 | use core::future::Future; | 1 | use core::future::Future; |
| 2 | use core::marker::PhantomData; | 2 | use core::marker::PhantomData; |
| 3 | use core::pin::Pin; | 3 | use core::pin::Pin; |
| 4 | use core::sync::atomic::{fence, Ordering}; | 4 | use core::sync::atomic::{fence, AtomicUsize, Ordering}; |
| 5 | use core::task::{Context, Poll, Waker}; | 5 | use core::task::{Context, Poll, Waker}; |
| 6 | 6 | ||
| 7 | use atomic_polyfill::AtomicUsize; | ||
| 8 | use embassy_hal_common::{into_ref, Peripheral, PeripheralRef}; | 7 | use embassy_hal_common::{into_ref, Peripheral, PeripheralRef}; |
| 9 | use embassy_sync::waitqueue::AtomicWaker; | 8 | use embassy_sync::waitqueue::AtomicWaker; |
| 10 | 9 | ||
diff --git a/embassy-stm32/src/eth/generic_smi.rs b/embassy-stm32/src/eth/generic_smi.rs index 968256046..90631b175 100644 --- a/embassy-stm32/src/eth/generic_smi.rs +++ b/embassy-stm32/src/eth/generic_smi.rs | |||
| @@ -1,5 +1,11 @@ | |||
| 1 | //! Generic SMI Ethernet PHY | 1 | //! Generic SMI Ethernet PHY |
| 2 | 2 | ||
| 3 | #[cfg(feature = "time")] | ||
| 4 | use embassy_time::{Duration, Timer}; | ||
| 5 | use futures::task::Context; | ||
| 6 | #[cfg(feature = "time")] | ||
| 7 | use futures::FutureExt; | ||
| 8 | |||
| 3 | use super::{StationManagement, PHY}; | 9 | use super::{StationManagement, PHY}; |
| 4 | 10 | ||
| 5 | #[allow(dead_code)] | 11 | #[allow(dead_code)] |
| @@ -36,25 +42,48 @@ mod phy_consts { | |||
| 36 | use self::phy_consts::*; | 42 | use self::phy_consts::*; |
| 37 | 43 | ||
| 38 | /// Generic SMI Ethernet PHY | 44 | /// Generic SMI Ethernet PHY |
| 39 | pub struct GenericSMI; | 45 | pub struct GenericSMI { |
| 46 | #[cfg(feature = "time")] | ||
| 47 | poll_interval: Duration, | ||
| 48 | } | ||
| 49 | |||
| 50 | impl GenericSMI { | ||
| 51 | #[cfg(feature = "time")] | ||
| 52 | pub fn new() -> Self { | ||
| 53 | Self { | ||
| 54 | poll_interval: Duration::from_millis(500), | ||
| 55 | } | ||
| 56 | } | ||
| 57 | |||
| 58 | #[cfg(not(feature = "time"))] | ||
| 59 | pub fn new() -> Self { | ||
| 60 | Self {} | ||
| 61 | } | ||
| 62 | } | ||
| 40 | 63 | ||
| 41 | unsafe impl PHY for GenericSMI { | 64 | unsafe impl PHY for GenericSMI { |
| 42 | /// Reset PHY and wait for it to come out of reset. | 65 | /// Reset PHY and wait for it to come out of reset. |
| 43 | fn phy_reset<S: StationManagement>(sm: &mut S) { | 66 | fn phy_reset<S: StationManagement>(&mut self, sm: &mut S) { |
| 44 | sm.smi_write(PHY_REG_BCR, PHY_REG_BCR_RESET); | 67 | sm.smi_write(PHY_REG_BCR, PHY_REG_BCR_RESET); |
| 45 | while sm.smi_read(PHY_REG_BCR) & PHY_REG_BCR_RESET == PHY_REG_BCR_RESET {} | 68 | while sm.smi_read(PHY_REG_BCR) & PHY_REG_BCR_RESET == PHY_REG_BCR_RESET {} |
| 46 | } | 69 | } |
| 47 | 70 | ||
| 48 | /// PHY initialisation. | 71 | /// PHY initialisation. |
| 49 | fn phy_init<S: StationManagement>(sm: &mut S) { | 72 | fn phy_init<S: StationManagement>(&mut self, sm: &mut S) { |
| 50 | // Clear WU CSR | 73 | // Clear WU CSR |
| 51 | Self::smi_write_ext(sm, PHY_REG_WUCSR, 0); | 74 | self.smi_write_ext(sm, PHY_REG_WUCSR, 0); |
| 52 | 75 | ||
| 53 | // Enable auto-negotiation | 76 | // Enable auto-negotiation |
| 54 | sm.smi_write(PHY_REG_BCR, PHY_REG_BCR_AN | PHY_REG_BCR_ANRST | PHY_REG_BCR_100M); | 77 | sm.smi_write(PHY_REG_BCR, PHY_REG_BCR_AN | PHY_REG_BCR_ANRST | PHY_REG_BCR_100M); |
| 55 | } | 78 | } |
| 56 | 79 | ||
| 57 | fn poll_link<S: StationManagement>(sm: &mut S) -> bool { | 80 | fn poll_link<S: StationManagement>(&mut self, sm: &mut S, cx: &mut Context) -> bool { |
| 81 | #[cfg(not(feature = "time"))] | ||
| 82 | cx.waker().wake_by_ref(); | ||
| 83 | |||
| 84 | #[cfg(feature = "time")] | ||
| 85 | let _ = Timer::after(self.poll_interval).poll_unpin(cx); | ||
| 86 | |||
| 58 | let bsr = sm.smi_read(PHY_REG_BSR); | 87 | let bsr = sm.smi_read(PHY_REG_BSR); |
| 59 | 88 | ||
| 60 | // No link without autonegotiate | 89 | // No link without autonegotiate |
| @@ -73,8 +102,12 @@ unsafe impl PHY for GenericSMI { | |||
| 73 | 102 | ||
| 74 | /// Public functions for the PHY | 103 | /// Public functions for the PHY |
| 75 | impl GenericSMI { | 104 | impl GenericSMI { |
| 105 | pub fn set_poll_interval(&mut self, poll_interval: Duration) { | ||
| 106 | self.poll_interval = poll_interval | ||
| 107 | } | ||
| 108 | |||
| 76 | // Writes a value to an extended PHY register in MMD address space | 109 | // Writes a value to an extended PHY register in MMD address space |
| 77 | fn smi_write_ext<S: StationManagement>(sm: &mut S, reg_addr: u16, reg_data: u16) { | 110 | fn smi_write_ext<S: StationManagement>(&mut self, sm: &mut S, reg_addr: u16, reg_data: u16) { |
| 78 | sm.smi_write(PHY_REG_CTL, 0x0003); // set address | 111 | sm.smi_write(PHY_REG_CTL, 0x0003); // set address |
| 79 | sm.smi_write(PHY_REG_ADDAR, reg_addr); | 112 | sm.smi_write(PHY_REG_ADDAR, reg_addr); |
| 80 | sm.smi_write(PHY_REG_CTL, 0x4003); // set data | 113 | sm.smi_write(PHY_REG_CTL, 0x4003); // set data |
diff --git a/embassy-stm32/src/eth/mod.rs b/embassy-stm32/src/eth/mod.rs index 4989e17c7..1687cb319 100644 --- a/embassy-stm32/src/eth/mod.rs +++ b/embassy-stm32/src/eth/mod.rs | |||
| @@ -81,9 +81,7 @@ impl<'d, T: Instance, P: PHY> embassy_net_driver::Driver for Ethernet<'d, T, P> | |||
| 81 | } | 81 | } |
| 82 | 82 | ||
| 83 | fn link_state(&mut self, cx: &mut Context) -> LinkState { | 83 | fn link_state(&mut self, cx: &mut Context) -> LinkState { |
| 84 | // TODO: wake cx.waker on link state change | 84 | if self.phy.poll_link(&mut self.station_management, cx) { |
| 85 | cx.waker().wake_by_ref(); | ||
| 86 | if P::poll_link(self) { | ||
| 87 | LinkState::Up | 85 | LinkState::Up |
| 88 | } else { | 86 | } else { |
| 89 | LinkState::Down | 87 | LinkState::Down |
| @@ -148,11 +146,11 @@ pub unsafe trait StationManagement { | |||
| 148 | /// The methods cannot move S | 146 | /// The methods cannot move S |
| 149 | pub unsafe trait PHY { | 147 | pub unsafe trait PHY { |
| 150 | /// Reset PHY and wait for it to come out of reset. | 148 | /// Reset PHY and wait for it to come out of reset. |
| 151 | fn phy_reset<S: StationManagement>(sm: &mut S); | 149 | fn phy_reset<S: StationManagement>(&mut self, sm: &mut S); |
| 152 | /// PHY initialisation. | 150 | /// PHY initialisation. |
| 153 | fn phy_init<S: StationManagement>(sm: &mut S); | 151 | fn phy_init<S: StationManagement>(&mut self, sm: &mut S); |
| 154 | /// Poll link to see if it is up and FD with 100Mbps | 152 | /// Poll link to see if it is up and FD with 100Mbps |
| 155 | fn poll_link<S: StationManagement>(sm: &mut S) -> bool; | 153 | fn poll_link<S: StationManagement>(&mut self, sm: &mut S, cx: &mut Context) -> bool; |
| 156 | } | 154 | } |
| 157 | 155 | ||
| 158 | pub(crate) mod sealed { | 156 | pub(crate) mod sealed { |
diff --git a/embassy-stm32/src/eth/v1/mod.rs b/embassy-stm32/src/eth/v1/mod.rs index b53c2d0fa..2a6ea35ff 100644 --- a/embassy-stm32/src/eth/v1/mod.rs +++ b/embassy-stm32/src/eth/v1/mod.rs | |||
| @@ -3,6 +3,7 @@ | |||
| 3 | mod rx_desc; | 3 | mod rx_desc; |
| 4 | mod tx_desc; | 4 | mod tx_desc; |
| 5 | 5 | ||
| 6 | use core::marker::PhantomData; | ||
| 6 | use core::sync::atomic::{fence, Ordering}; | 7 | use core::sync::atomic::{fence, Ordering}; |
| 7 | 8 | ||
| 8 | use embassy_hal_common::{into_ref, PeripheralRef}; | 9 | use embassy_hal_common::{into_ref, PeripheralRef}; |
| @@ -48,9 +49,8 @@ pub struct Ethernet<'d, T: Instance, P: PHY> { | |||
| 48 | pub(crate) rx: RDesRing<'d>, | 49 | pub(crate) rx: RDesRing<'d>, |
| 49 | 50 | ||
| 50 | pins: [PeripheralRef<'d, AnyPin>; 9], | 51 | pins: [PeripheralRef<'d, AnyPin>; 9], |
| 51 | _phy: P, | 52 | pub(crate) phy: P, |
| 52 | clock_range: Cr, | 53 | pub(crate) station_management: EthernetStationManagement<T>, |
| 53 | phy_addr: u8, | ||
| 54 | pub(crate) mac_addr: [u8; 6], | 54 | pub(crate) mac_addr: [u8; 6], |
| 55 | } | 55 | } |
| 56 | 56 | ||
| @@ -224,9 +224,12 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> { | |||
| 224 | let mut this = Self { | 224 | let mut this = Self { |
| 225 | _peri: peri, | 225 | _peri: peri, |
| 226 | pins, | 226 | pins, |
| 227 | _phy: phy, | 227 | phy: phy, |
| 228 | clock_range, | 228 | station_management: EthernetStationManagement { |
| 229 | phy_addr, | 229 | peri: PhantomData, |
| 230 | clock_range: clock_range, | ||
| 231 | phy_addr: phy_addr, | ||
| 232 | }, | ||
| 230 | mac_addr, | 233 | mac_addr, |
| 231 | tx: TDesRing::new(&mut queue.tx_desc, &mut queue.tx_buf), | 234 | tx: TDesRing::new(&mut queue.tx_desc, &mut queue.tx_buf), |
| 232 | rx: RDesRing::new(&mut queue.rx_desc, &mut queue.rx_buf), | 235 | rx: RDesRing::new(&mut queue.rx_desc, &mut queue.rx_buf), |
| @@ -256,8 +259,8 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> { | |||
| 256 | w.set_tie(true); | 259 | w.set_tie(true); |
| 257 | }); | 260 | }); |
| 258 | 261 | ||
| 259 | P::phy_reset(&mut this); | 262 | this.phy.phy_reset(&mut this.station_management); |
| 260 | P::phy_init(&mut this); | 263 | this.phy.phy_init(&mut this.station_management); |
| 261 | 264 | ||
| 262 | interrupt::ETH.unpend(); | 265 | interrupt::ETH.unpend(); |
| 263 | unsafe { interrupt::ETH.enable() }; | 266 | unsafe { interrupt::ETH.enable() }; |
| @@ -266,7 +269,13 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> { | |||
| 266 | } | 269 | } |
| 267 | } | 270 | } |
| 268 | 271 | ||
| 269 | unsafe impl<'d, T: Instance, P: PHY> StationManagement for Ethernet<'d, T, P> { | 272 | pub struct EthernetStationManagement<T: Instance> { |
| 273 | peri: PhantomData<T>, | ||
| 274 | clock_range: Cr, | ||
| 275 | phy_addr: u8, | ||
| 276 | } | ||
| 277 | |||
| 278 | unsafe impl<T: Instance> StationManagement for EthernetStationManagement<T> { | ||
| 270 | fn smi_read(&mut self, reg: u8) -> u16 { | 279 | fn smi_read(&mut self, reg: u8) -> u16 { |
| 271 | let mac = ETH.ethernet_mac(); | 280 | let mac = ETH.ethernet_mac(); |
| 272 | 281 | ||
diff --git a/embassy-stm32/src/eth/v2/mod.rs b/embassy-stm32/src/eth/v2/mod.rs index 600e1d3bc..bb681c42b 100644 --- a/embassy-stm32/src/eth/v2/mod.rs +++ b/embassy-stm32/src/eth/v2/mod.rs | |||
| @@ -1,5 +1,6 @@ | |||
| 1 | mod descriptors; | 1 | mod descriptors; |
| 2 | 2 | ||
| 3 | use core::marker::PhantomData; | ||
| 3 | use core::sync::atomic::{fence, Ordering}; | 4 | use core::sync::atomic::{fence, Ordering}; |
| 4 | 5 | ||
| 5 | use embassy_hal_common::{into_ref, PeripheralRef}; | 6 | use embassy_hal_common::{into_ref, PeripheralRef}; |
| @@ -40,9 +41,8 @@ pub struct Ethernet<'d, T: Instance, P: PHY> { | |||
| 40 | pub(crate) tx: TDesRing<'d>, | 41 | pub(crate) tx: TDesRing<'d>, |
| 41 | pub(crate) rx: RDesRing<'d>, | 42 | pub(crate) rx: RDesRing<'d>, |
| 42 | pins: [PeripheralRef<'d, AnyPin>; 9], | 43 | pins: [PeripheralRef<'d, AnyPin>; 9], |
| 43 | _phy: P, | 44 | pub(crate) phy: P, |
| 44 | clock_range: u8, | 45 | pub(crate) station_management: EthernetStationManagement<T>, |
| 45 | phy_addr: u8, | ||
| 46 | pub(crate) mac_addr: [u8; 6], | 46 | pub(crate) mac_addr: [u8; 6], |
| 47 | } | 47 | } |
| 48 | 48 | ||
| @@ -201,9 +201,12 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> { | |||
| 201 | tx: TDesRing::new(&mut queue.tx_desc, &mut queue.tx_buf), | 201 | tx: TDesRing::new(&mut queue.tx_desc, &mut queue.tx_buf), |
| 202 | rx: RDesRing::new(&mut queue.rx_desc, &mut queue.rx_buf), | 202 | rx: RDesRing::new(&mut queue.rx_desc, &mut queue.rx_buf), |
| 203 | pins, | 203 | pins, |
| 204 | _phy: phy, | 204 | phy: phy, |
| 205 | clock_range, | 205 | station_management: EthernetStationManagement { |
| 206 | phy_addr, | 206 | peri: PhantomData, |
| 207 | clock_range: clock_range, | ||
| 208 | phy_addr: phy_addr, | ||
| 209 | }, | ||
| 207 | mac_addr, | 210 | mac_addr, |
| 208 | }; | 211 | }; |
| 209 | 212 | ||
| @@ -229,8 +232,8 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> { | |||
| 229 | w.set_tie(true); | 232 | w.set_tie(true); |
| 230 | }); | 233 | }); |
| 231 | 234 | ||
| 232 | P::phy_reset(&mut this); | 235 | this.phy.phy_reset(&mut this.station_management); |
| 233 | P::phy_init(&mut this); | 236 | this.phy.phy_init(&mut this.station_management); |
| 234 | 237 | ||
| 235 | interrupt::ETH.unpend(); | 238 | interrupt::ETH.unpend(); |
| 236 | unsafe { interrupt::ETH.enable() }; | 239 | unsafe { interrupt::ETH.enable() }; |
| @@ -239,7 +242,13 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> { | |||
| 239 | } | 242 | } |
| 240 | } | 243 | } |
| 241 | 244 | ||
| 242 | unsafe impl<'d, T: Instance, P: PHY> StationManagement for Ethernet<'d, T, P> { | 245 | pub struct EthernetStationManagement<T: Instance> { |
| 246 | peri: PhantomData<T>, | ||
| 247 | clock_range: u8, | ||
| 248 | phy_addr: u8, | ||
| 249 | } | ||
| 250 | |||
| 251 | unsafe impl<T: Instance> StationManagement for EthernetStationManagement<T> { | ||
| 243 | fn smi_read(&mut self, reg: u8) -> u16 { | 252 | fn smi_read(&mut self, reg: u8) -> u16 { |
| 244 | let mac = ETH.ethernet_mac(); | 253 | let mac = ETH.ethernet_mac(); |
| 245 | 254 | ||
diff --git a/embassy-stm32/src/flash/asynch.rs b/embassy-stm32/src/flash/asynch.rs index 70a5ded62..f175349cd 100644 --- a/embassy-stm32/src/flash/asynch.rs +++ b/embassy-stm32/src/flash/asynch.rs | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | use core::marker::PhantomData; | 1 | use core::marker::PhantomData; |
| 2 | use core::sync::atomic::{fence, Ordering}; | ||
| 2 | 3 | ||
| 3 | use atomic_polyfill::{fence, Ordering}; | ||
| 4 | use embassy_hal_common::drop::OnDrop; | 4 | use embassy_hal_common::drop::OnDrop; |
| 5 | use embassy_hal_common::into_ref; | 5 | use embassy_hal_common::into_ref; |
| 6 | use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; | 6 | use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; |
diff --git a/embassy-stm32/src/flash/common.rs b/embassy-stm32/src/flash/common.rs index c6cdc574b..2a374733d 100644 --- a/embassy-stm32/src/flash/common.rs +++ b/embassy-stm32/src/flash/common.rs | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | use core::marker::PhantomData; | 1 | use core::marker::PhantomData; |
| 2 | use core::sync::atomic::{fence, Ordering}; | ||
| 2 | 3 | ||
| 3 | use atomic_polyfill::{fence, Ordering}; | ||
| 4 | use embassy_hal_common::drop::OnDrop; | 4 | use embassy_hal_common::drop::OnDrop; |
| 5 | use embassy_hal_common::{into_ref, PeripheralRef}; | 5 | use embassy_hal_common::{into_ref, PeripheralRef}; |
| 6 | use stm32_metapac::FLASH_BASE; | 6 | use stm32_metapac::FLASH_BASE; |
diff --git a/embassy-stm32/src/flash/f0.rs b/embassy-stm32/src/flash/f0.rs index 02bd4cc1f..ec8343e7c 100644 --- a/embassy-stm32/src/flash/f0.rs +++ b/embassy-stm32/src/flash/f0.rs | |||
| @@ -1,7 +1,6 @@ | |||
| 1 | use core::convert::TryInto; | 1 | use core::convert::TryInto; |
| 2 | use core::ptr::write_volatile; | 2 | use core::ptr::write_volatile; |
| 3 | 3 | use core::sync::atomic::{fence, Ordering}; | |
| 4 | use atomic_polyfill::{fence, Ordering}; | ||
| 5 | 4 | ||
| 6 | use super::{FlashRegion, FlashSector, FLASH_REGIONS, WRITE_SIZE}; | 5 | use super::{FlashRegion, FlashSector, FLASH_REGIONS, WRITE_SIZE}; |
| 7 | use crate::flash::Error; | 6 | use crate::flash::Error; |
diff --git a/embassy-stm32/src/flash/f3.rs b/embassy-stm32/src/flash/f3.rs index b093a7837..40335d643 100644 --- a/embassy-stm32/src/flash/f3.rs +++ b/embassy-stm32/src/flash/f3.rs | |||
| @@ -1,7 +1,6 @@ | |||
| 1 | use core::convert::TryInto; | 1 | use core::convert::TryInto; |
| 2 | use core::ptr::write_volatile; | 2 | use core::ptr::write_volatile; |
| 3 | 3 | use core::sync::atomic::{fence, Ordering}; | |
| 4 | use atomic_polyfill::{fence, Ordering}; | ||
| 5 | 4 | ||
| 6 | use super::{FlashRegion, FlashSector, FLASH_REGIONS, WRITE_SIZE}; | 5 | use super::{FlashRegion, FlashSector, FLASH_REGIONS, WRITE_SIZE}; |
| 7 | use crate::flash::Error; | 6 | use crate::flash::Error; |
diff --git a/embassy-stm32/src/flash/f4.rs b/embassy-stm32/src/flash/f4.rs index 242d99278..4cb39e033 100644 --- a/embassy-stm32/src/flash/f4.rs +++ b/embassy-stm32/src/flash/f4.rs | |||
| @@ -1,8 +1,7 @@ | |||
| 1 | use core::convert::TryInto; | 1 | use core::convert::TryInto; |
| 2 | use core::ptr::write_volatile; | 2 | use core::ptr::write_volatile; |
| 3 | use core::sync::atomic::{fence, Ordering}; | 3 | use core::sync::atomic::{fence, AtomicBool, Ordering}; |
| 4 | 4 | ||
| 5 | use atomic_polyfill::AtomicBool; | ||
| 6 | use embassy_sync::waitqueue::AtomicWaker; | 5 | use embassy_sync::waitqueue::AtomicWaker; |
| 7 | use pac::flash::regs::Sr; | 6 | use pac::flash::regs::Sr; |
| 8 | use pac::FLASH_SIZE; | 7 | use pac::FLASH_SIZE; |
diff --git a/embassy-stm32/src/flash/h7.rs b/embassy-stm32/src/flash/h7.rs index 9baf059ee..bf17b5b18 100644 --- a/embassy-stm32/src/flash/h7.rs +++ b/embassy-stm32/src/flash/h7.rs | |||
| @@ -1,7 +1,6 @@ | |||
| 1 | use core::convert::TryInto; | 1 | use core::convert::TryInto; |
| 2 | use core::ptr::write_volatile; | 2 | use core::ptr::write_volatile; |
| 3 | 3 | use core::sync::atomic::{fence, Ordering}; | |
| 4 | use atomic_polyfill::{fence, Ordering}; | ||
| 5 | 4 | ||
| 6 | use super::{FlashRegion, FlashSector, BANK1_REGION, FLASH_REGIONS, WRITE_SIZE}; | 5 | use super::{FlashRegion, FlashSector, BANK1_REGION, FLASH_REGIONS, WRITE_SIZE}; |
| 7 | use crate::flash::Error; | 6 | use crate::flash::Error; |
diff --git a/embassy-stm32/src/flash/l.rs b/embassy-stm32/src/flash/l.rs index deefd05ed..243c8b51d 100644 --- a/embassy-stm32/src/flash/l.rs +++ b/embassy-stm32/src/flash/l.rs | |||
| @@ -1,6 +1,5 @@ | |||
| 1 | use core::ptr::write_volatile; | 1 | use core::ptr::write_volatile; |
| 2 | 2 | use core::sync::atomic::{fence, Ordering}; | |
| 3 | use atomic_polyfill::{fence, Ordering}; | ||
| 4 | 3 | ||
| 5 | use super::{FlashRegion, FlashSector, FLASH_REGIONS, WRITE_SIZE}; | 4 | use super::{FlashRegion, FlashSector, FLASH_REGIONS, WRITE_SIZE}; |
| 6 | use crate::flash::Error; | 5 | use crate::flash::Error; |
diff --git a/embassy-stm32/src/fmc.rs b/embassy-stm32/src/fmc.rs index a4f3b9686..60d7a00ee 100644 --- a/embassy-stm32/src/fmc.rs +++ b/embassy-stm32/src/fmc.rs | |||
| @@ -86,6 +86,24 @@ macro_rules! fmc_sdram_constructor { | |||
| 86 | } | 86 | } |
| 87 | 87 | ||
| 88 | impl<'d, T: Instance> Fmc<'d, T> { | 88 | impl<'d, T: Instance> Fmc<'d, T> { |
| 89 | fmc_sdram_constructor!(sdram_a12bits_d16bits_4banks_bank1: ( | ||
| 90 | bank: stm32_fmc::SdramTargetBank::Bank1, | ||
| 91 | addr: [ | ||
| 92 | (a0: A0Pin), (a1: A1Pin), (a2: A2Pin), (a3: A3Pin), (a4: A4Pin), (a5: A5Pin), (a6: A6Pin), (a7: A7Pin), (a8: A8Pin), (a9: A9Pin), (a10: A10Pin), (a11: A11Pin) | ||
| 93 | ], | ||
| 94 | ba: [(ba0: BA0Pin), (ba1: BA1Pin)], | ||
| 95 | d: [ | ||
| 96 | (d0: D0Pin), (d1: D1Pin), (d2: D2Pin), (d3: D3Pin), (d4: D4Pin), (d5: D5Pin), (d6: D6Pin), (d7: D7Pin), | ||
| 97 | (d8: D8Pin), (d9: D9Pin), (d10: D10Pin), (d11: D11Pin), (d12: D12Pin), (d13: D13Pin), (d14: D14Pin), (d15: D15Pin) | ||
| 98 | ], | ||
| 99 | nbl: [ | ||
| 100 | (nbl0: NBL0Pin), (nbl1: NBL1Pin) | ||
| 101 | ], | ||
| 102 | ctrl: [ | ||
| 103 | (sdcke: SDCKE0Pin), (sdclk: SDCLKPin), (sdncas: SDNCASPin), (sdne: SDNE0Pin), (sdnras: SDNRASPin), (sdnwe: SDNWEPin) | ||
| 104 | ] | ||
| 105 | )); | ||
| 106 | |||
| 89 | fmc_sdram_constructor!(sdram_a12bits_d32bits_4banks_bank1: ( | 107 | fmc_sdram_constructor!(sdram_a12bits_d32bits_4banks_bank1: ( |
| 90 | bank: stm32_fmc::SdramTargetBank::Bank1, | 108 | bank: stm32_fmc::SdramTargetBank::Bank1, |
| 91 | addr: [ | 109 | addr: [ |
diff --git a/embassy-stm32/src/i2c/v2.rs b/embassy-stm32/src/i2c/v2.rs index 1f036d55c..208d1527d 100644 --- a/embassy-stm32/src/i2c/v2.rs +++ b/embassy-stm32/src/i2c/v2.rs | |||
| @@ -382,13 +382,18 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { | |||
| 382 | // I2C start | 382 | // I2C start |
| 383 | // | 383 | // |
| 384 | // ST SAD+W | 384 | // ST SAD+W |
| 385 | Self::master_write( | 385 | if let Err(err) = Self::master_write( |
| 386 | address, | 386 | address, |
| 387 | write.len().min(255), | 387 | write.len().min(255), |
| 388 | Stop::Software, | 388 | Stop::Software, |
| 389 | last_chunk_idx != 0, | 389 | last_chunk_idx != 0, |
| 390 | &check_timeout, | 390 | &check_timeout, |
| 391 | )?; | 391 | ) { |
| 392 | if send_stop { | ||
| 393 | self.master_stop(); | ||
| 394 | } | ||
| 395 | return Err(err); | ||
| 396 | } | ||
| 392 | 397 | ||
| 393 | for (number, chunk) in write.chunks(255).enumerate() { | 398 | for (number, chunk) in write.chunks(255).enumerate() { |
| 394 | if number != 0 { | 399 | if number != 0 { |
| @@ -399,18 +404,22 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { | |||
| 399 | // Wait until we are allowed to send data | 404 | // Wait until we are allowed to send data |
| 400 | // (START has been ACKed or last byte when | 405 | // (START has been ACKed or last byte when |
| 401 | // through) | 406 | // through) |
| 402 | self.wait_txe(&check_timeout)?; | 407 | if let Err(err) = self.wait_txe(&check_timeout) { |
| 408 | if send_stop { | ||
| 409 | self.master_stop(); | ||
| 410 | } | ||
| 411 | return Err(err); | ||
| 412 | } | ||
| 403 | 413 | ||
| 404 | T::regs().txdr().write(|w| w.set_txdata(*byte)); | 414 | T::regs().txdr().write(|w| w.set_txdata(*byte)); |
| 405 | } | 415 | } |
| 406 | } | 416 | } |
| 407 | // Wait until the write finishes | 417 | // Wait until the write finishes |
| 408 | self.wait_tc(&check_timeout)?; | 418 | let result = self.wait_tc(&check_timeout); |
| 409 | |||
| 410 | if send_stop { | 419 | if send_stop { |
| 411 | self.master_stop(); | 420 | self.master_stop(); |
| 412 | } | 421 | } |
| 413 | Ok(()) | 422 | result |
| 414 | } | 423 | } |
| 415 | 424 | ||
| 416 | async fn write_dma_internal( | 425 | async fn write_dma_internal( |
| @@ -707,13 +716,16 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { | |||
| 707 | let first_length = write[0].len(); | 716 | let first_length = write[0].len(); |
| 708 | let last_slice_index = write.len() - 1; | 717 | let last_slice_index = write.len() - 1; |
| 709 | 718 | ||
| 710 | Self::master_write( | 719 | if let Err(err) = Self::master_write( |
| 711 | address, | 720 | address, |
| 712 | first_length.min(255), | 721 | first_length.min(255), |
| 713 | Stop::Software, | 722 | Stop::Software, |
| 714 | (first_length > 255) || (last_slice_index != 0), | 723 | (first_length > 255) || (last_slice_index != 0), |
| 715 | &check_timeout, | 724 | &check_timeout, |
| 716 | )?; | 725 | ) { |
| 726 | self.master_stop(); | ||
| 727 | return Err(err); | ||
| 728 | } | ||
| 717 | 729 | ||
| 718 | for (idx, slice) in write.iter().enumerate() { | 730 | for (idx, slice) in write.iter().enumerate() { |
| 719 | let slice_len = slice.len(); | 731 | let slice_len = slice.len(); |
| @@ -726,27 +738,36 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { | |||
| 726 | let last_chunk_idx = total_chunks.saturating_sub(1); | 738 | let last_chunk_idx = total_chunks.saturating_sub(1); |
| 727 | 739 | ||
| 728 | if idx != 0 { | 740 | if idx != 0 { |
| 729 | Self::master_continue( | 741 | if let Err(err) = Self::master_continue( |
| 730 | slice_len.min(255), | 742 | slice_len.min(255), |
| 731 | (idx != last_slice_index) || (slice_len > 255), | 743 | (idx != last_slice_index) || (slice_len > 255), |
| 732 | &check_timeout, | 744 | &check_timeout, |
| 733 | )?; | 745 | ) { |
| 746 | self.master_stop(); | ||
| 747 | return Err(err); | ||
| 748 | } | ||
| 734 | } | 749 | } |
| 735 | 750 | ||
| 736 | for (number, chunk) in slice.chunks(255).enumerate() { | 751 | for (number, chunk) in slice.chunks(255).enumerate() { |
| 737 | if number != 0 { | 752 | if number != 0 { |
| 738 | Self::master_continue( | 753 | if let Err(err) = Self::master_continue( |
| 739 | chunk.len(), | 754 | chunk.len(), |
| 740 | (number != last_chunk_idx) || (idx != last_slice_index), | 755 | (number != last_chunk_idx) || (idx != last_slice_index), |
| 741 | &check_timeout, | 756 | &check_timeout, |
| 742 | )?; | 757 | ) { |
| 758 | self.master_stop(); | ||
| 759 | return Err(err); | ||
| 760 | } | ||
| 743 | } | 761 | } |
| 744 | 762 | ||
| 745 | for byte in chunk { | 763 | for byte in chunk { |
| 746 | // Wait until we are allowed to send data | 764 | // Wait until we are allowed to send data |
| 747 | // (START has been ACKed or last byte when | 765 | // (START has been ACKed or last byte when |
| 748 | // through) | 766 | // through) |
| 749 | self.wait_txe(&check_timeout)?; | 767 | if let Err(err) = self.wait_txe(&check_timeout) { |
| 768 | self.master_stop(); | ||
| 769 | return Err(err); | ||
| 770 | } | ||
| 750 | 771 | ||
| 751 | // Put byte on the wire | 772 | // Put byte on the wire |
| 752 | //self.i2c.txdr.write(|w| w.txdata().bits(*byte)); | 773 | //self.i2c.txdr.write(|w| w.txdata().bits(*byte)); |
| @@ -755,10 +776,9 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { | |||
| 755 | } | 776 | } |
| 756 | } | 777 | } |
| 757 | // Wait until the write finishes | 778 | // Wait until the write finishes |
| 758 | self.wait_tc(&check_timeout)?; | 779 | let result = self.wait_tc(&check_timeout); |
| 759 | self.master_stop(); | 780 | self.master_stop(); |
| 760 | 781 | result | |
| 761 | Ok(()) | ||
| 762 | } | 782 | } |
| 763 | 783 | ||
| 764 | pub fn blocking_write_vectored(&mut self, address: u8, write: &[&[u8]]) -> Result<(), Error> { | 784 | pub fn blocking_write_vectored(&mut self, address: u8, write: &[&[u8]]) -> Result<(), Error> { |
diff --git a/embassy-stm32/src/ipcc.rs b/embassy-stm32/src/ipcc.rs index 37f840c73..a24cba9f0 100644 --- a/embassy-stm32/src/ipcc.rs +++ b/embassy-stm32/src/ipcc.rs | |||
| @@ -1,8 +1,7 @@ | |||
| 1 | use core::future::poll_fn; | 1 | use core::future::poll_fn; |
| 2 | use core::sync::atomic::{compiler_fence, Ordering}; | ||
| 2 | use core::task::Poll; | 3 | use core::task::Poll; |
| 3 | 4 | ||
| 4 | use atomic_polyfill::{compiler_fence, Ordering}; | ||
| 5 | |||
| 6 | use self::sealed::Instance; | 5 | use self::sealed::Instance; |
| 7 | use crate::interrupt; | 6 | use crate::interrupt; |
| 8 | use crate::interrupt::typelevel::Interrupt; | 7 | use crate::interrupt::typelevel::Interrupt; |
diff --git a/embassy-stm32/src/rcc/h5.rs b/embassy-stm32/src/rcc/h5.rs index 4025a4e05..7e2f75ab7 100644 --- a/embassy-stm32/src/rcc/h5.rs +++ b/embassy-stm32/src/rcc/h5.rs | |||
| @@ -473,11 +473,11 @@ fn init_pll(num: usize, config: Option<Pll>, input: &PllInput) -> PllOutput { | |||
| 473 | w.set_divm(0); | 473 | w.set_divm(0); |
| 474 | }); | 474 | }); |
| 475 | 475 | ||
| 476 | return PllOutput{ | 476 | return PllOutput { |
| 477 | p: None, | 477 | p: None, |
| 478 | q: None, | 478 | q: None, |
| 479 | r: None, | 479 | r: None, |
| 480 | } | 480 | }; |
| 481 | }; | 481 | }; |
| 482 | 482 | ||
| 483 | assert!(1 <= config.prediv && config.prediv <= 63); | 483 | assert!(1 <= config.prediv && config.prediv <= 63); |
diff --git a/embassy-stm32/src/rcc/h7.rs b/embassy-stm32/src/rcc/h7.rs index f3a98c794..7e5cd0d1a 100644 --- a/embassy-stm32/src/rcc/h7.rs +++ b/embassy-stm32/src/rcc/h7.rs | |||
| @@ -740,7 +740,7 @@ mod pll { | |||
| 740 | } | 740 | } |
| 741 | }; | 741 | }; |
| 742 | 742 | ||
| 743 | let vco_ck = output + pll_x_p; | 743 | let vco_ck = output * pll_x_p; |
| 744 | 744 | ||
| 745 | assert!(pll_x_p < 128); | 745 | assert!(pll_x_p < 128); |
| 746 | assert!(vco_ck >= VCO_MIN); | 746 | assert!(vco_ck >= VCO_MIN); |
diff --git a/embassy-stm32/src/rcc/l4.rs b/embassy-stm32/src/rcc/l4.rs index 20cb8c91c..8a9b4adbf 100644 --- a/embassy-stm32/src/rcc/l4.rs +++ b/embassy-stm32/src/rcc/l4.rs | |||
| @@ -1,6 +1,7 @@ | |||
| 1 | use core::marker::PhantomData; | 1 | use core::marker::PhantomData; |
| 2 | 2 | ||
| 3 | use embassy_hal_common::into_ref; | 3 | use embassy_hal_common::into_ref; |
| 4 | use stm32_metapac::rcc::regs::Cfgr; | ||
| 4 | use stm32_metapac::rcc::vals::{Lsedrv, Mcopre, Mcosel}; | 5 | use stm32_metapac::rcc::vals::{Lsedrv, Mcopre, Mcosel}; |
| 5 | 6 | ||
| 6 | use crate::gpio::sealed::AFType; | 7 | use crate::gpio::sealed::AFType; |
| @@ -439,6 +440,26 @@ impl<'d, T: McoInstance> Mco<'d, T> { | |||
| 439 | } | 440 | } |
| 440 | 441 | ||
| 441 | pub(crate) unsafe fn init(config: Config) { | 442 | pub(crate) unsafe fn init(config: Config) { |
| 443 | // Switch to MSI to prevent problems with PLL configuration. | ||
| 444 | if !RCC.cr().read().msion() { | ||
| 445 | // Turn on MSI and configure it to 4MHz. | ||
| 446 | RCC.cr().modify(|w| { | ||
| 447 | w.set_msirgsel(true); // MSI Range is provided by MSIRANGE[3:0]. | ||
| 448 | w.set_msirange(MSIRange::default().into()); | ||
| 449 | w.set_msipllen(false); | ||
| 450 | w.set_msion(true) | ||
| 451 | }); | ||
| 452 | |||
| 453 | // Wait until MSI is running | ||
| 454 | while !RCC.cr().read().msirdy() {} | ||
| 455 | } | ||
| 456 | if RCC.cfgr().read().sws() != Sw::MSI { | ||
| 457 | // Set MSI as a clock source, reset prescalers. | ||
| 458 | RCC.cfgr().write_value(Cfgr::default()); | ||
| 459 | // Wait for clock switch status bits to change. | ||
| 460 | while RCC.cfgr().read().sws() != Sw::MSI {} | ||
| 461 | } | ||
| 462 | |||
| 442 | match config.rtc_mux { | 463 | match config.rtc_mux { |
| 443 | RtcClockSource::LSE32 => { | 464 | RtcClockSource::LSE32 => { |
| 444 | // 1. Unlock the backup domain | 465 | // 1. Unlock the backup domain |
| @@ -660,6 +681,8 @@ pub(crate) unsafe fn init(config: Config) { | |||
| 660 | } | 681 | } |
| 661 | }; | 682 | }; |
| 662 | 683 | ||
| 684 | RCC.apb1enr1().modify(|w| w.set_pwren(true)); | ||
| 685 | |||
| 663 | set_freqs(Clocks { | 686 | set_freqs(Clocks { |
| 664 | sys: Hertz(sys_clk), | 687 | sys: Hertz(sys_clk), |
| 665 | ahb1: Hertz(ahb_freq), | 688 | ahb1: Hertz(ahb_freq), |
diff --git a/embassy-stm32/src/rcc/mod.rs b/embassy-stm32/src/rcc/mod.rs index d6816d6a8..886fc0b93 100644 --- a/embassy-stm32/src/rcc/mod.rs +++ b/embassy-stm32/src/rcc/mod.rs | |||
| @@ -83,12 +83,12 @@ static mut CLOCK_FREQS: MaybeUninit<Clocks> = MaybeUninit::uninit(); | |||
| 83 | /// Safety: Sets a mutable global. | 83 | /// Safety: Sets a mutable global. |
| 84 | pub(crate) unsafe fn set_freqs(freqs: Clocks) { | 84 | pub(crate) unsafe fn set_freqs(freqs: Clocks) { |
| 85 | debug!("rcc: {:?}", freqs); | 85 | debug!("rcc: {:?}", freqs); |
| 86 | CLOCK_FREQS.as_mut_ptr().write(freqs); | 86 | CLOCK_FREQS = MaybeUninit::new(freqs); |
| 87 | } | 87 | } |
| 88 | 88 | ||
| 89 | /// Safety: Reads a mutable global. | 89 | /// Safety: Reads a mutable global. |
| 90 | pub(crate) unsafe fn get_freqs() -> &'static Clocks { | 90 | pub(crate) unsafe fn get_freqs() -> &'static Clocks { |
| 91 | &*CLOCK_FREQS.as_ptr() | 91 | CLOCK_FREQS.assume_init_ref() |
| 92 | } | 92 | } |
| 93 | 93 | ||
| 94 | #[cfg(feature = "unstable-pac")] | 94 | #[cfg(feature = "unstable-pac")] |
diff --git a/embassy-stm32/src/rcc/wl.rs b/embassy-stm32/src/rcc/wl.rs index 7072db984..6b69bb1cb 100644 --- a/embassy-stm32/src/rcc/wl.rs +++ b/embassy-stm32/src/rcc/wl.rs | |||
| @@ -1,4 +1,5 @@ | |||
| 1 | use crate::pac::{FLASH, RCC}; | 1 | use crate::pac::pwr::vals::Dbp; |
| 2 | use crate::pac::{FLASH, PWR, RCC}; | ||
| 2 | use crate::rcc::{set_freqs, Clocks}; | 3 | use crate::rcc::{set_freqs, Clocks}; |
| 3 | use crate::time::Hertz; | 4 | use crate::time::Hertz; |
| 4 | 5 | ||
| @@ -184,6 +185,8 @@ pub struct Config { | |||
| 184 | pub apb1_pre: APBPrescaler, | 185 | pub apb1_pre: APBPrescaler, |
| 185 | pub apb2_pre: APBPrescaler, | 186 | pub apb2_pre: APBPrescaler, |
| 186 | pub enable_lsi: bool, | 187 | pub enable_lsi: bool, |
| 188 | pub enable_rtc_apb: bool, | ||
| 189 | pub rtc_mux: RtcClockSource, | ||
| 187 | } | 190 | } |
| 188 | 191 | ||
| 189 | impl Default for Config { | 192 | impl Default for Config { |
| @@ -196,10 +199,25 @@ impl Default for Config { | |||
| 196 | apb1_pre: APBPrescaler::NotDivided, | 199 | apb1_pre: APBPrescaler::NotDivided, |
| 197 | apb2_pre: APBPrescaler::NotDivided, | 200 | apb2_pre: APBPrescaler::NotDivided, |
| 198 | enable_lsi: false, | 201 | enable_lsi: false, |
| 202 | enable_rtc_apb: false, | ||
| 203 | rtc_mux: RtcClockSource::LSI32, | ||
| 199 | } | 204 | } |
| 200 | } | 205 | } |
| 201 | } | 206 | } |
| 202 | 207 | ||
| 208 | pub enum RtcClockSource { | ||
| 209 | LSE32, | ||
| 210 | LSI32, | ||
| 211 | } | ||
| 212 | |||
| 213 | #[repr(u8)] | ||
| 214 | pub enum Lsedrv { | ||
| 215 | Low = 0, | ||
| 216 | MediumLow = 1, | ||
| 217 | MediumHigh = 2, | ||
| 218 | High = 3, | ||
| 219 | } | ||
| 220 | |||
| 203 | pub(crate) unsafe fn init(config: Config) { | 221 | pub(crate) unsafe fn init(config: Config) { |
| 204 | let (sys_clk, sw, vos) = match config.mux { | 222 | let (sys_clk, sw, vos) = match config.mux { |
| 205 | ClockSrc::HSI16 => (HSI_FREQ.0, 0x01, VoltageScale::Range2), | 223 | ClockSrc::HSI16 => (HSI_FREQ.0, 0x01, VoltageScale::Range2), |
| @@ -266,6 +284,32 @@ pub(crate) unsafe fn init(config: Config) { | |||
| 266 | 284 | ||
| 267 | while FLASH.acr().read().latency() != ws {} | 285 | while FLASH.acr().read().latency() != ws {} |
| 268 | 286 | ||
| 287 | match config.rtc_mux { | ||
| 288 | RtcClockSource::LSE32 => { | ||
| 289 | // 1. Unlock the backup domain | ||
| 290 | PWR.cr1().modify(|w| w.set_dbp(Dbp::ENABLED)); | ||
| 291 | |||
| 292 | // 2. Setup the LSE | ||
| 293 | RCC.bdcr().modify(|w| { | ||
| 294 | // Enable LSE | ||
| 295 | w.set_lseon(true); | ||
| 296 | // Max drive strength | ||
| 297 | // TODO: should probably be settable | ||
| 298 | w.set_lsedrv(Lsedrv::High as u8); //---// PAM - should not be commented | ||
| 299 | }); | ||
| 300 | |||
| 301 | // Wait until LSE is running | ||
| 302 | while !RCC.bdcr().read().lserdy() {} | ||
| 303 | } | ||
| 304 | RtcClockSource::LSI32 => { | ||
| 305 | // Turn on the internal 32 kHz LSI oscillator | ||
| 306 | RCC.csr().modify(|w| w.set_lsion(true)); | ||
| 307 | |||
| 308 | // Wait until LSI is running | ||
| 309 | while !RCC.csr().read().lsirdy() {} | ||
| 310 | } | ||
| 311 | } | ||
| 312 | |||
| 269 | match config.mux { | 313 | match config.mux { |
| 270 | ClockSrc::HSI16 => { | 314 | ClockSrc::HSI16 => { |
| 271 | // Enable HSI16 | 315 | // Enable HSI16 |
| @@ -287,11 +331,26 @@ pub(crate) unsafe fn init(config: Config) { | |||
| 287 | w.set_msirgsel(true); | 331 | w.set_msirgsel(true); |
| 288 | w.set_msirange(range.into()); | 332 | w.set_msirange(range.into()); |
| 289 | w.set_msion(true); | 333 | w.set_msion(true); |
| 334 | |||
| 335 | if let RtcClockSource::LSE32 = config.rtc_mux { | ||
| 336 | // If LSE is enabled, enable calibration of MSI | ||
| 337 | w.set_msipllen(true); | ||
| 338 | } else { | ||
| 339 | w.set_msipllen(false); | ||
| 340 | } | ||
| 290 | }); | 341 | }); |
| 291 | while !RCC.cr().read().msirdy() {} | 342 | while !RCC.cr().read().msirdy() {} |
| 292 | } | 343 | } |
| 293 | } | 344 | } |
| 294 | 345 | ||
| 346 | if config.enable_rtc_apb { | ||
| 347 | // enable peripheral clock for communication | ||
| 348 | crate::pac::RCC.apb1enr1().modify(|w| w.set_rtcapben(true)); | ||
| 349 | |||
| 350 | // read to allow the pwr clock to enable | ||
| 351 | crate::pac::PWR.cr1().read(); | ||
| 352 | } | ||
| 353 | |||
| 295 | RCC.extcfgr().modify(|w| { | 354 | RCC.extcfgr().modify(|w| { |
| 296 | if config.shd_ahb_pre == AHBPrescaler::NotDivided { | 355 | if config.shd_ahb_pre == AHBPrescaler::NotDivided { |
| 297 | w.set_shdhpre(0); | 356 | w.set_shdhpre(0); |
diff --git a/embassy-stm32/src/rtc/v3.rs b/embassy-stm32/src/rtc/v3.rs index 7e5c64d90..8ef0ec51d 100644 --- a/embassy-stm32/src/rtc/v3.rs +++ b/embassy-stm32/src/rtc/v3.rs | |||
| @@ -172,6 +172,7 @@ impl sealed::Instance for crate::peripherals::RTC { | |||
| 172 | const BACKUP_REGISTER_COUNT: usize = 32; | 172 | const BACKUP_REGISTER_COUNT: usize = 32; |
| 173 | 173 | ||
| 174 | fn read_backup_register(_rtc: &Rtc, register: usize) -> Option<u32> { | 174 | fn read_backup_register(_rtc: &Rtc, register: usize) -> Option<u32> { |
| 175 | #[allow(clippy::if_same_then_else)] | ||
| 175 | if register < Self::BACKUP_REGISTER_COUNT { | 176 | if register < Self::BACKUP_REGISTER_COUNT { |
| 176 | //Some(rtc.bkpr()[register].read().bits()) | 177 | //Some(rtc.bkpr()[register].read().bits()) |
| 177 | None // RTC3 backup registers come from the TAMP peripe=heral, not RTC. Not() even in the L412 PAC | 178 | None // RTC3 backup registers come from the TAMP peripe=heral, not RTC. Not() even in the L412 PAC |
diff --git a/embassy-stm32/src/spi/mod.rs b/embassy-stm32/src/spi/mod.rs index c3224073d..d5f63f84e 100644 --- a/embassy-stm32/src/spi/mod.rs +++ b/embassy-stm32/src/spi/mod.rs | |||
| @@ -852,25 +852,19 @@ mod eh1 { | |||
| 852 | type Error = Error; | 852 | type Error = Error; |
| 853 | } | 853 | } |
| 854 | 854 | ||
| 855 | impl<'d, T: Instance, Tx, Rx> embedded_hal_1::spi::SpiBusFlush for Spi<'d, T, Tx, Rx> { | 855 | impl<'d, T: Instance, W: Word, Tx, Rx> embedded_hal_1::spi::SpiBus<W> for Spi<'d, T, Tx, Rx> { |
| 856 | fn flush(&mut self) -> Result<(), Self::Error> { | 856 | fn flush(&mut self) -> Result<(), Self::Error> { |
| 857 | Ok(()) | 857 | Ok(()) |
| 858 | } | 858 | } |
| 859 | } | ||
| 860 | 859 | ||
| 861 | impl<'d, T: Instance, W: Word, Tx, Rx> embedded_hal_1::spi::SpiBusRead<W> for Spi<'d, T, Tx, Rx> { | ||
| 862 | fn read(&mut self, words: &mut [W]) -> Result<(), Self::Error> { | 860 | fn read(&mut self, words: &mut [W]) -> Result<(), Self::Error> { |
| 863 | self.blocking_read(words) | 861 | self.blocking_read(words) |
| 864 | } | 862 | } |
| 865 | } | ||
| 866 | 863 | ||
| 867 | impl<'d, T: Instance, W: Word, Tx, Rx> embedded_hal_1::spi::SpiBusWrite<W> for Spi<'d, T, Tx, Rx> { | ||
| 868 | fn write(&mut self, words: &[W]) -> Result<(), Self::Error> { | 864 | fn write(&mut self, words: &[W]) -> Result<(), Self::Error> { |
| 869 | self.blocking_write(words) | 865 | self.blocking_write(words) |
| 870 | } | 866 | } |
| 871 | } | ||
| 872 | 867 | ||
| 873 | impl<'d, T: Instance, W: Word, Tx, Rx> embedded_hal_1::spi::SpiBus<W> for Spi<'d, T, Tx, Rx> { | ||
| 874 | fn transfer(&mut self, read: &mut [W], write: &[W]) -> Result<(), Self::Error> { | 868 | fn transfer(&mut self, read: &mut [W], write: &[W]) -> Result<(), Self::Error> { |
| 875 | self.blocking_transfer(read, write) | 869 | self.blocking_transfer(read, write) |
| 876 | } | 870 | } |
| @@ -895,32 +889,25 @@ mod eh1 { | |||
| 895 | #[cfg(all(feature = "unstable-traits", feature = "nightly"))] | 889 | #[cfg(all(feature = "unstable-traits", feature = "nightly"))] |
| 896 | mod eha { | 890 | mod eha { |
| 897 | use super::*; | 891 | use super::*; |
| 898 | impl<'d, T: Instance, Tx, Rx> embedded_hal_async::spi::SpiBusFlush for Spi<'d, T, Tx, Rx> { | 892 | |
| 893 | impl<'d, T: Instance, Tx: TxDma<T>, Rx: RxDma<T>, W: Word> embedded_hal_async::spi::SpiBus<W> for Spi<'d, T, Tx, Rx> { | ||
| 899 | async fn flush(&mut self) -> Result<(), Self::Error> { | 894 | async fn flush(&mut self) -> Result<(), Self::Error> { |
| 900 | Ok(()) | 895 | Ok(()) |
| 901 | } | 896 | } |
| 902 | } | ||
| 903 | 897 | ||
| 904 | impl<'d, T: Instance, Tx: TxDma<T>, Rx, W: Word> embedded_hal_async::spi::SpiBusWrite<W> for Spi<'d, T, Tx, Rx> { | ||
| 905 | async fn write(&mut self, words: &[W]) -> Result<(), Self::Error> { | 898 | async fn write(&mut self, words: &[W]) -> Result<(), Self::Error> { |
| 906 | self.write(words).await | 899 | self.write(words).await |
| 907 | } | 900 | } |
| 908 | } | ||
| 909 | 901 | ||
| 910 | impl<'d, T: Instance, Tx: TxDma<T>, Rx: RxDma<T>, W: Word> embedded_hal_async::spi::SpiBusRead<W> | ||
| 911 | for Spi<'d, T, Tx, Rx> | ||
| 912 | { | ||
| 913 | async fn read(&mut self, words: &mut [W]) -> Result<(), Self::Error> { | 902 | async fn read(&mut self, words: &mut [W]) -> Result<(), Self::Error> { |
| 914 | self.read(words).await | 903 | self.read(words).await |
| 915 | } | 904 | } |
| 916 | } | ||
| 917 | 905 | ||
| 918 | impl<'d, T: Instance, Tx: TxDma<T>, Rx: RxDma<T>, W: Word> embedded_hal_async::spi::SpiBus<W> for Spi<'d, T, Tx, Rx> { | 906 | async fn transfer(&mut self, read: &mut [W], write: &[W]) -> Result<(), Self::Error> { |
| 919 | async fn transfer<'a>(&'a mut self, read: &'a mut [W], write: &'a [W]) -> Result<(), Self::Error> { | ||
| 920 | self.transfer(read, write).await | 907 | self.transfer(read, write).await |
| 921 | } | 908 | } |
| 922 | 909 | ||
| 923 | async fn transfer_in_place<'a>(&'a mut self, words: &'a mut [W]) -> Result<(), Self::Error> { | 910 | async fn transfer_in_place(&mut self, words: &mut [W]) -> Result<(), Self::Error> { |
| 924 | self.transfer_in_place(words).await | 911 | self.transfer_in_place(words).await |
| 925 | } | 912 | } |
| 926 | } | 913 | } |
diff --git a/embassy-stm32/src/usb_otg/usb.rs b/embassy-stm32/src/usb_otg/usb.rs index 6783db28d..fd0e22adf 100644 --- a/embassy-stm32/src/usb_otg/usb.rs +++ b/embassy-stm32/src/usb_otg/usb.rs | |||
| @@ -1,8 +1,8 @@ | |||
| 1 | use core::cell::UnsafeCell; | 1 | use core::cell::UnsafeCell; |
| 2 | use core::marker::PhantomData; | 2 | use core::marker::PhantomData; |
| 3 | use core::sync::atomic::{AtomicBool, AtomicU16, Ordering}; | ||
| 3 | use core::task::Poll; | 4 | use core::task::Poll; |
| 4 | 5 | ||
| 5 | use atomic_polyfill::{AtomicBool, AtomicU16, Ordering}; | ||
| 6 | use embassy_hal_common::{into_ref, Peripheral}; | 6 | use embassy_hal_common::{into_ref, Peripheral}; |
| 7 | use embassy_sync::waitqueue::AtomicWaker; | 7 | use embassy_sync::waitqueue::AtomicWaker; |
| 8 | use embassy_usb_driver::{ | 8 | use embassy_usb_driver::{ |
| @@ -648,7 +648,7 @@ impl<'d, T: Instance> Bus<'d, T> { | |||
| 648 | 648 | ||
| 649 | let r = T::regs(); | 649 | let r = T::regs(); |
| 650 | let core_id = r.cid().read().0; | 650 | let core_id = r.cid().read().0; |
| 651 | info!("Core id {:08x}", core_id); | 651 | trace!("Core id {:08x}", core_id); |
| 652 | 652 | ||
| 653 | // Wait for AHB ready. | 653 | // Wait for AHB ready. |
| 654 | while !r.grstctl().read().ahbidl() {} | 654 | while !r.grstctl().read().ahbidl() {} |
| @@ -1154,14 +1154,22 @@ impl<'d, T: Instance> embassy_usb_driver::EndpointOut for Endpoint<'d, T, Out> { | |||
| 1154 | trace!("read start len={}", buf.len()); | 1154 | trace!("read start len={}", buf.len()); |
| 1155 | 1155 | ||
| 1156 | poll_fn(|cx| { | 1156 | poll_fn(|cx| { |
| 1157 | let r = T::regs(); | ||
| 1157 | let index = self.info.addr.index(); | 1158 | let index = self.info.addr.index(); |
| 1158 | let state = T::state(); | 1159 | let state = T::state(); |
| 1159 | 1160 | ||
| 1160 | state.ep_out_wakers[index].register(cx.waker()); | 1161 | state.ep_out_wakers[index].register(cx.waker()); |
| 1161 | 1162 | ||
| 1163 | let doepctl = r.doepctl(index).read(); | ||
| 1164 | trace!("read ep={:?}: doepctl {:08x}", self.info.addr, doepctl.0,); | ||
| 1165 | if !doepctl.usbaep() { | ||
| 1166 | trace!("read ep={:?} error disabled", self.info.addr); | ||
| 1167 | return Poll::Ready(Err(EndpointError::Disabled)); | ||
| 1168 | } | ||
| 1169 | |||
| 1162 | let len = state.ep_out_size[index].load(Ordering::Relaxed); | 1170 | let len = state.ep_out_size[index].load(Ordering::Relaxed); |
| 1163 | if len != EP_OUT_BUFFER_EMPTY { | 1171 | if len != EP_OUT_BUFFER_EMPTY { |
| 1164 | trace!("read done len={}", len); | 1172 | trace!("read ep={:?} done len={}", self.info.addr, len); |
| 1165 | 1173 | ||
| 1166 | if len as usize > buf.len() { | 1174 | if len as usize > buf.len() { |
| 1167 | return Poll::Ready(Err(EndpointError::BufferOverflow)); | 1175 | return Poll::Ready(Err(EndpointError::BufferOverflow)); |
| @@ -1214,7 +1222,12 @@ impl<'d, T: Instance> embassy_usb_driver::EndpointIn for Endpoint<'d, T, In> { | |||
| 1214 | 1222 | ||
| 1215 | let diepctl = r.diepctl(index).read(); | 1223 | let diepctl = r.diepctl(index).read(); |
| 1216 | let dtxfsts = r.dtxfsts(index).read(); | 1224 | let dtxfsts = r.dtxfsts(index).read(); |
| 1217 | info!("diepctl {:08x} ftxfsts {:08x}", diepctl.0, dtxfsts.0); | 1225 | trace!( |
| 1226 | "write ep={:?}: diepctl {:08x} ftxfsts {:08x}", | ||
| 1227 | self.info.addr, | ||
| 1228 | diepctl.0, | ||
| 1229 | dtxfsts.0 | ||
| 1230 | ); | ||
| 1218 | if !diepctl.usbaep() { | 1231 | if !diepctl.usbaep() { |
| 1219 | trace!("write ep={:?} wait for prev: error disabled", self.info.addr); | 1232 | trace!("write ep={:?} wait for prev: error disabled", self.info.addr); |
| 1220 | Poll::Ready(Err(EndpointError::Disabled)) | 1233 | Poll::Ready(Err(EndpointError::Disabled)) |
diff --git a/embassy-time/CHANGELOG.md b/embassy-time/CHANGELOG.md index f4a7860e6..26640d930 100644 --- a/embassy-time/CHANGELOG.md +++ b/embassy-time/CHANGELOG.md | |||
| @@ -5,6 +5,11 @@ All notable changes to this project will be documented in this file. | |||
| 5 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), | 5 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), |
| 6 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). | 6 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). |
| 7 | 7 | ||
| 8 | ## 0.1.2 - 2023-07-05 | ||
| 9 | |||
| 10 | - Update `embedded-hal-async` to `0.2.0-alpha.2`. | ||
| 11 | - Update `embedded-hal v1` to `1.0.0-alpha.11`. (Note: v0.2 support is kept unchanged). | ||
| 12 | |||
| 8 | ## 0.1.1 - 2023-04-13 | 13 | ## 0.1.1 - 2023-04-13 |
| 9 | 14 | ||
| 10 | - Update `embedded-hal-async` to `0.2.0-alpha.1` (uses `async fn` in traits). | 15 | - Update `embedded-hal-async` to `0.2.0-alpha.1` (uses `async fn` in traits). |
diff --git a/embassy-time/Cargo.toml b/embassy-time/Cargo.toml index 857da5467..0afb1103d 100644 --- a/embassy-time/Cargo.toml +++ b/embassy-time/Cargo.toml | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | [package] | 1 | [package] |
| 2 | name = "embassy-time" | 2 | name = "embassy-time" |
| 3 | version = "0.1.1" | 3 | version = "0.1.2" |
| 4 | edition = "2021" | 4 | edition = "2021" |
| 5 | description = "Instant and Duration for embedded no-std systems, with async timer support" | 5 | description = "Instant and Duration for embedded no-std systems, with async timer support" |
| 6 | repository = "https://github.com/embassy-rs/embassy" | 6 | repository = "https://github.com/embassy-rs/embassy" |
| @@ -23,7 +23,7 @@ target = "x86_64-unknown-linux-gnu" | |||
| 23 | features = ["nightly", "defmt", "unstable-traits", "std"] | 23 | features = ["nightly", "defmt", "unstable-traits", "std"] |
| 24 | 24 | ||
| 25 | [features] | 25 | [features] |
| 26 | std = ["tick-hz-1_000_000"] | 26 | std = ["tick-hz-1_000_000", "critical-section/std"] |
| 27 | wasm = ["dep:wasm-bindgen", "dep:js-sys", "dep:wasm-timer", "tick-hz-1_000_000"] | 27 | wasm = ["dep:wasm-bindgen", "dep:js-sys", "dep:wasm-timer", "tick-hz-1_000_000"] |
| 28 | 28 | ||
| 29 | # Enable nightly-only features | 29 | # Enable nightly-only features |
| @@ -152,8 +152,8 @@ defmt = { version = "0.3", optional = true } | |||
| 152 | log = { version = "0.4.14", optional = true } | 152 | log = { version = "0.4.14", optional = true } |
| 153 | 153 | ||
| 154 | embedded-hal-02 = { package = "embedded-hal", version = "0.2.6" } | 154 | embedded-hal-02 = { package = "embedded-hal", version = "0.2.6" } |
| 155 | embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-alpha.10", optional = true} | 155 | embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-alpha.11", optional = true} |
| 156 | embedded-hal-async = { version = "=0.2.0-alpha.1", optional = true} | 156 | embedded-hal-async = { version = "=0.2.0-alpha.2", optional = true} |
| 157 | 157 | ||
| 158 | futures-util = { version = "0.3.17", default-features = false } | 158 | futures-util = { version = "0.3.17", default-features = false } |
| 159 | atomic-polyfill = "1.0.1" | 159 | atomic-polyfill = "1.0.1" |
diff --git a/embassy-time/src/driver.rs b/embassy-time/src/driver.rs index d6436369b..5fe7becaf 100644 --- a/embassy-time/src/driver.rs +++ b/embassy-time/src/driver.rs | |||
| @@ -36,7 +36,7 @@ | |||
| 36 | //! ``` | 36 | //! ``` |
| 37 | //! use embassy_time::driver::{Driver, AlarmHandle}; | 37 | //! use embassy_time::driver::{Driver, AlarmHandle}; |
| 38 | //! | 38 | //! |
| 39 | //! struct MyDriver{}; // not public! | 39 | //! struct MyDriver{} // not public! |
| 40 | //! embassy_time::time_driver_impl!(static DRIVER: MyDriver = MyDriver{}); | 40 | //! embassy_time::time_driver_impl!(static DRIVER: MyDriver = MyDriver{}); |
| 41 | //! | 41 | //! |
| 42 | //! impl Driver for MyDriver { | 42 | //! impl Driver for MyDriver { |
diff --git a/embassy-time/src/driver_std.rs b/embassy-time/src/driver_std.rs index 9f8c57b5c..32db47a37 100644 --- a/embassy-time/src/driver_std.rs +++ b/embassy-time/src/driver_std.rs | |||
| @@ -1,10 +1,10 @@ | |||
| 1 | use core::sync::atomic::{AtomicU8, Ordering}; | ||
| 1 | use std::cell::{RefCell, UnsafeCell}; | 2 | use std::cell::{RefCell, UnsafeCell}; |
| 2 | use std::mem::MaybeUninit; | 3 | use std::mem::MaybeUninit; |
| 3 | use std::sync::{Condvar, Mutex, Once}; | 4 | use std::sync::{Condvar, Mutex, Once}; |
| 4 | use std::time::{Duration as StdDuration, Instant as StdInstant}; | 5 | use std::time::{Duration as StdDuration, Instant as StdInstant}; |
| 5 | use std::{mem, ptr, thread}; | 6 | use std::{mem, ptr, thread}; |
| 6 | 7 | ||
| 7 | use atomic_polyfill::{AtomicU8, Ordering}; | ||
| 8 | use critical_section::Mutex as CsMutex; | 8 | use critical_section::Mutex as CsMutex; |
| 9 | 9 | ||
| 10 | use crate::driver::{AlarmHandle, Driver}; | 10 | use crate::driver::{AlarmHandle, Driver}; |
diff --git a/embassy-time/src/driver_wasm.rs b/embassy-time/src/driver_wasm.rs index 63d049897..0f672dc75 100644 --- a/embassy-time/src/driver_wasm.rs +++ b/embassy-time/src/driver_wasm.rs | |||
| @@ -1,9 +1,9 @@ | |||
| 1 | use core::sync::atomic::{AtomicU8, Ordering}; | ||
| 1 | use std::cell::UnsafeCell; | 2 | use std::cell::UnsafeCell; |
| 2 | use std::mem::MaybeUninit; | 3 | use std::mem::MaybeUninit; |
| 3 | use std::ptr; | 4 | use std::ptr; |
| 4 | use std::sync::{Mutex, Once}; | 5 | use std::sync::{Mutex, Once}; |
| 5 | 6 | ||
| 6 | use atomic_polyfill::{AtomicU8, Ordering}; | ||
| 7 | use wasm_bindgen::prelude::*; | 7 | use wasm_bindgen::prelude::*; |
| 8 | use wasm_timer::Instant as StdInstant; | 8 | use wasm_timer::Instant as StdInstant; |
| 9 | 9 | ||
diff --git a/embassy-time/src/queue_generic.rs b/embassy-time/src/queue_generic.rs index 4795eb2f3..77947ab29 100644 --- a/embassy-time/src/queue_generic.rs +++ b/embassy-time/src/queue_generic.rs | |||
| @@ -16,7 +16,7 @@ const QUEUE_SIZE: usize = 16; | |||
| 16 | #[cfg(feature = "generic-queue-32")] | 16 | #[cfg(feature = "generic-queue-32")] |
| 17 | const QUEUE_SIZE: usize = 32; | 17 | const QUEUE_SIZE: usize = 32; |
| 18 | #[cfg(feature = "generic-queue-64")] | 18 | #[cfg(feature = "generic-queue-64")] |
| 19 | const QUEUE_SIZE: usize = 32; | 19 | const QUEUE_SIZE: usize = 64; |
| 20 | #[cfg(feature = "generic-queue-128")] | 20 | #[cfg(feature = "generic-queue-128")] |
| 21 | const QUEUE_SIZE: usize = 128; | 21 | const QUEUE_SIZE: usize = 128; |
| 22 | #[cfg(not(any( | 22 | #[cfg(not(any( |
diff --git a/examples/boot/application/nrf/Cargo.toml b/examples/boot/application/nrf/Cargo.toml index b98f73f39..2a0cf7818 100644 --- a/examples/boot/application/nrf/Cargo.toml +++ b/examples/boot/application/nrf/Cargo.toml | |||
| @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" | |||
| 7 | [dependencies] | 7 | [dependencies] |
| 8 | embassy-sync = { version = "0.2.0", path = "../../../../embassy-sync" } | 8 | embassy-sync = { version = "0.2.0", path = "../../../../embassy-sync" } |
| 9 | embassy-executor = { version = "0.2.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "nightly", "integrated-timers", "arch-cortex-m", "executor-thread"] } | 9 | embassy-executor = { version = "0.2.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "nightly", "integrated-timers", "arch-cortex-m", "executor-thread"] } |
| 10 | embassy-time = { version = "0.1.0", path = "../../../../embassy-time", features = ["nightly"] } | 10 | embassy-time = { version = "0.1.2", path = "../../../../embassy-time", features = ["nightly"] } |
| 11 | embassy-nrf = { version = "0.1.0", path = "../../../../embassy-nrf", features = ["time-driver-rtc1", "gpiote", "nightly"] } | 11 | embassy-nrf = { version = "0.1.0", path = "../../../../embassy-nrf", features = ["time-driver-rtc1", "gpiote", "nightly"] } |
| 12 | embassy-boot = { version = "0.1.0", path = "../../../../embassy-boot/boot", features = ["nightly"] } | 12 | embassy-boot = { version = "0.1.0", path = "../../../../embassy-boot/boot", features = ["nightly"] } |
| 13 | embassy-boot-nrf = { version = "0.1.0", path = "../../../../embassy-boot/nrf", features = ["nightly"] } | 13 | embassy-boot-nrf = { version = "0.1.0", path = "../../../../embassy-boot/nrf", features = ["nightly"] } |
diff --git a/examples/boot/application/rp/Cargo.toml b/examples/boot/application/rp/Cargo.toml index 007b6839c..95b2da954 100644 --- a/examples/boot/application/rp/Cargo.toml +++ b/examples/boot/application/rp/Cargo.toml | |||
| @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" | |||
| 7 | [dependencies] | 7 | [dependencies] |
| 8 | embassy-sync = { version = "0.2.0", path = "../../../../embassy-sync" } | 8 | embassy-sync = { version = "0.2.0", path = "../../../../embassy-sync" } |
| 9 | embassy-executor = { version = "0.2.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "nightly", "integrated-timers", "arch-cortex-m", "executor-thread"] } | 9 | embassy-executor = { version = "0.2.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "nightly", "integrated-timers", "arch-cortex-m", "executor-thread"] } |
| 10 | embassy-time = { version = "0.1.0", path = "../../../../embassy-time", features = ["nightly"] } | 10 | embassy-time = { version = "0.1.2", path = "../../../../embassy-time", features = ["nightly"] } |
| 11 | embassy-rp = { version = "0.1.0", path = "../../../../embassy-rp", features = ["time-driver", "unstable-traits", "nightly"] } | 11 | embassy-rp = { version = "0.1.0", path = "../../../../embassy-rp", features = ["time-driver", "unstable-traits", "nightly"] } |
| 12 | embassy-boot-rp = { version = "0.1.0", path = "../../../../embassy-boot/rp", features = ["nightly"] } | 12 | embassy-boot-rp = { version = "0.1.0", path = "../../../../embassy-boot/rp", features = ["nightly"] } |
| 13 | embassy-embedded-hal = { version = "0.1.0", path = "../../../../embassy-embedded-hal" } | 13 | embassy-embedded-hal = { version = "0.1.0", path = "../../../../embassy-embedded-hal" } |
diff --git a/examples/boot/application/stm32f3/Cargo.toml b/examples/boot/application/stm32f3/Cargo.toml index 5b3faf8f8..3b0fc4d9d 100644 --- a/examples/boot/application/stm32f3/Cargo.toml +++ b/examples/boot/application/stm32f3/Cargo.toml | |||
| @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" | |||
| 7 | [dependencies] | 7 | [dependencies] |
| 8 | embassy-sync = { version = "0.2.0", path = "../../../../embassy-sync", features = ["defmt"] } | 8 | embassy-sync = { version = "0.2.0", path = "../../../../embassy-sync", features = ["defmt"] } |
| 9 | embassy-executor = { version = "0.2.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "nightly", "integrated-timers"] } | 9 | embassy-executor = { version = "0.2.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "nightly", "integrated-timers"] } |
| 10 | embassy-time = { version = "0.1.0", path = "../../../../embassy-time", features = ["nightly", "tick-hz-32_768"] } | 10 | embassy-time = { version = "0.1.2", path = "../../../../embassy-time", features = ["nightly", "tick-hz-32_768"] } |
| 11 | embassy-stm32 = { version = "0.1.0", path = "../../../../embassy-stm32", features = ["unstable-traits", "nightly", "stm32f303re", "time-driver-any", "exti"] } | 11 | embassy-stm32 = { version = "0.1.0", path = "../../../../embassy-stm32", features = ["unstable-traits", "nightly", "stm32f303re", "time-driver-any", "exti"] } |
| 12 | embassy-boot-stm32 = { version = "0.1.0", path = "../../../../embassy-boot/stm32", features = ["nightly"] } | 12 | embassy-boot-stm32 = { version = "0.1.0", path = "../../../../embassy-boot/stm32", features = ["nightly"] } |
| 13 | embassy-embedded-hal = { version = "0.1.0", path = "../../../../embassy-embedded-hal" } | 13 | embassy-embedded-hal = { version = "0.1.0", path = "../../../../embassy-embedded-hal" } |
diff --git a/examples/boot/application/stm32f7/Cargo.toml b/examples/boot/application/stm32f7/Cargo.toml index b6a6f9cd8..323b4ab2c 100644 --- a/examples/boot/application/stm32f7/Cargo.toml +++ b/examples/boot/application/stm32f7/Cargo.toml | |||
| @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" | |||
| 7 | [dependencies] | 7 | [dependencies] |
| 8 | embassy-sync = { version = "0.2.0", path = "../../../../embassy-sync", features = ["defmt"] } | 8 | embassy-sync = { version = "0.2.0", path = "../../../../embassy-sync", features = ["defmt"] } |
| 9 | embassy-executor = { version = "0.2.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "nightly", "integrated-timers"] } | 9 | embassy-executor = { version = "0.2.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "nightly", "integrated-timers"] } |
| 10 | embassy-time = { version = "0.1.0", path = "../../../../embassy-time", features = ["nightly", "tick-hz-32_768"] } | 10 | embassy-time = { version = "0.1.2", path = "../../../../embassy-time", features = ["nightly", "tick-hz-32_768"] } |
| 11 | embassy-stm32 = { version = "0.1.0", path = "../../../../embassy-stm32", features = ["unstable-traits", "nightly", "stm32f767zi", "time-driver-any", "exti"] } | 11 | embassy-stm32 = { version = "0.1.0", path = "../../../../embassy-stm32", features = ["unstable-traits", "nightly", "stm32f767zi", "time-driver-any", "exti"] } |
| 12 | embassy-boot-stm32 = { version = "0.1.0", path = "../../../../embassy-boot/stm32", features = ["nightly"] } | 12 | embassy-boot-stm32 = { version = "0.1.0", path = "../../../../embassy-boot/stm32", features = ["nightly"] } |
| 13 | embassy-embedded-hal = { version = "0.1.0", path = "../../../../embassy-embedded-hal" } | 13 | embassy-embedded-hal = { version = "0.1.0", path = "../../../../embassy-embedded-hal" } |
diff --git a/examples/boot/application/stm32h7/Cargo.toml b/examples/boot/application/stm32h7/Cargo.toml index 0a7e19b1d..b2abdc891 100644 --- a/examples/boot/application/stm32h7/Cargo.toml +++ b/examples/boot/application/stm32h7/Cargo.toml | |||
| @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" | |||
| 7 | [dependencies] | 7 | [dependencies] |
| 8 | embassy-sync = { version = "0.2.0", path = "../../../../embassy-sync" } | 8 | embassy-sync = { version = "0.2.0", path = "../../../../embassy-sync" } |
| 9 | embassy-executor = { version = "0.2.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "nightly", "integrated-timers"] } | 9 | embassy-executor = { version = "0.2.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "nightly", "integrated-timers"] } |
| 10 | embassy-time = { version = "0.1.0", path = "../../../../embassy-time", features = ["nightly", "tick-hz-32_768"] } | 10 | embassy-time = { version = "0.1.2", path = "../../../../embassy-time", features = ["nightly", "tick-hz-32_768"] } |
| 11 | embassy-stm32 = { version = "0.1.0", path = "../../../../embassy-stm32", features = ["unstable-traits", "nightly", "stm32h743zi", "time-driver-any", "exti"] } | 11 | embassy-stm32 = { version = "0.1.0", path = "../../../../embassy-stm32", features = ["unstable-traits", "nightly", "stm32h743zi", "time-driver-any", "exti"] } |
| 12 | embassy-boot-stm32 = { version = "0.1.0", path = "../../../../embassy-boot/stm32", features = ["nightly"] } | 12 | embassy-boot-stm32 = { version = "0.1.0", path = "../../../../embassy-boot/stm32", features = ["nightly"] } |
| 13 | embassy-embedded-hal = { version = "0.1.0", path = "../../../../embassy-embedded-hal" } | 13 | embassy-embedded-hal = { version = "0.1.0", path = "../../../../embassy-embedded-hal" } |
diff --git a/examples/boot/application/stm32l0/Cargo.toml b/examples/boot/application/stm32l0/Cargo.toml index 998df4dc0..0b7e72d5e 100644 --- a/examples/boot/application/stm32l0/Cargo.toml +++ b/examples/boot/application/stm32l0/Cargo.toml | |||
| @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" | |||
| 7 | [dependencies] | 7 | [dependencies] |
| 8 | embassy-sync = { version = "0.2.0", path = "../../../../embassy-sync", features = ["defmt"] } | 8 | embassy-sync = { version = "0.2.0", path = "../../../../embassy-sync", features = ["defmt"] } |
| 9 | embassy-executor = { version = "0.2.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "nightly", "integrated-timers"] } | 9 | embassy-executor = { version = "0.2.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "nightly", "integrated-timers"] } |
| 10 | embassy-time = { version = "0.1.0", path = "../../../../embassy-time", features = ["nightly", "tick-hz-32_768"] } | 10 | embassy-time = { version = "0.1.2", path = "../../../../embassy-time", features = ["nightly", "tick-hz-32_768"] } |
| 11 | embassy-stm32 = { version = "0.1.0", path = "../../../../embassy-stm32", features = ["unstable-traits", "nightly", "stm32l072cz", "time-driver-any", "exti", "memory-x"] } | 11 | embassy-stm32 = { version = "0.1.0", path = "../../../../embassy-stm32", features = ["unstable-traits", "nightly", "stm32l072cz", "time-driver-any", "exti", "memory-x"] } |
| 12 | embassy-boot-stm32 = { version = "0.1.0", path = "../../../../embassy-boot/stm32", features = ["nightly"] } | 12 | embassy-boot-stm32 = { version = "0.1.0", path = "../../../../embassy-boot/stm32", features = ["nightly"] } |
| 13 | embassy-embedded-hal = { version = "0.1.0", path = "../../../../embassy-embedded-hal" } | 13 | embassy-embedded-hal = { version = "0.1.0", path = "../../../../embassy-embedded-hal" } |
diff --git a/examples/boot/application/stm32l1/Cargo.toml b/examples/boot/application/stm32l1/Cargo.toml index 10b58c172..5f3f365c1 100644 --- a/examples/boot/application/stm32l1/Cargo.toml +++ b/examples/boot/application/stm32l1/Cargo.toml | |||
| @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" | |||
| 7 | [dependencies] | 7 | [dependencies] |
| 8 | embassy-sync = { version = "0.2.0", path = "../../../../embassy-sync", features = ["defmt"] } | 8 | embassy-sync = { version = "0.2.0", path = "../../../../embassy-sync", features = ["defmt"] } |
| 9 | embassy-executor = { version = "0.2.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "nightly", "integrated-timers"] } | 9 | embassy-executor = { version = "0.2.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "nightly", "integrated-timers"] } |
| 10 | embassy-time = { version = "0.1.0", path = "../../../../embassy-time", features = ["nightly", "tick-hz-32_768"] } | 10 | embassy-time = { version = "0.1.2", path = "../../../../embassy-time", features = ["nightly", "tick-hz-32_768"] } |
| 11 | embassy-stm32 = { version = "0.1.0", path = "../../../../embassy-stm32", features = ["unstable-traits", "nightly", "stm32l151cb-a", "time-driver-any", "exti"] } | 11 | embassy-stm32 = { version = "0.1.0", path = "../../../../embassy-stm32", features = ["unstable-traits", "nightly", "stm32l151cb-a", "time-driver-any", "exti"] } |
| 12 | embassy-boot-stm32 = { version = "0.1.0", path = "../../../../embassy-boot/stm32", features = ["nightly"] } | 12 | embassy-boot-stm32 = { version = "0.1.0", path = "../../../../embassy-boot/stm32", features = ["nightly"] } |
| 13 | embassy-embedded-hal = { version = "0.1.0", path = "../../../../embassy-embedded-hal" } | 13 | embassy-embedded-hal = { version = "0.1.0", path = "../../../../embassy-embedded-hal" } |
diff --git a/examples/boot/application/stm32l4/Cargo.toml b/examples/boot/application/stm32l4/Cargo.toml index 713a6527e..44eb5aba8 100644 --- a/examples/boot/application/stm32l4/Cargo.toml +++ b/examples/boot/application/stm32l4/Cargo.toml | |||
| @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" | |||
| 7 | [dependencies] | 7 | [dependencies] |
| 8 | embassy-sync = { version = "0.2.0", path = "../../../../embassy-sync", features = ["defmt"] } | 8 | embassy-sync = { version = "0.2.0", path = "../../../../embassy-sync", features = ["defmt"] } |
| 9 | embassy-executor = { version = "0.2.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "nightly", "integrated-timers"] } | 9 | embassy-executor = { version = "0.2.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "nightly", "integrated-timers"] } |
| 10 | embassy-time = { version = "0.1.0", path = "../../../../embassy-time", features = ["nightly", "tick-hz-32_768"] } | 10 | embassy-time = { version = "0.1.2", path = "../../../../embassy-time", features = ["nightly", "tick-hz-32_768"] } |
| 11 | embassy-stm32 = { version = "0.1.0", path = "../../../../embassy-stm32", features = ["unstable-traits", "nightly", "stm32l475vg", "time-driver-any", "exti"] } | 11 | embassy-stm32 = { version = "0.1.0", path = "../../../../embassy-stm32", features = ["unstable-traits", "nightly", "stm32l475vg", "time-driver-any", "exti"] } |
| 12 | embassy-boot-stm32 = { version = "0.1.0", path = "../../../../embassy-boot/stm32", features = ["nightly"] } | 12 | embassy-boot-stm32 = { version = "0.1.0", path = "../../../../embassy-boot/stm32", features = ["nightly"] } |
| 13 | embassy-embedded-hal = { version = "0.1.0", path = "../../../../embassy-embedded-hal" } | 13 | embassy-embedded-hal = { version = "0.1.0", path = "../../../../embassy-embedded-hal" } |
diff --git a/examples/boot/application/stm32wl/Cargo.toml b/examples/boot/application/stm32wl/Cargo.toml index 4c8bbd73f..fdad55060 100644 --- a/examples/boot/application/stm32wl/Cargo.toml +++ b/examples/boot/application/stm32wl/Cargo.toml | |||
| @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" | |||
| 7 | [dependencies] | 7 | [dependencies] |
| 8 | embassy-sync = { version = "0.2.0", path = "../../../../embassy-sync", features = ["defmt"] } | 8 | embassy-sync = { version = "0.2.0", path = "../../../../embassy-sync", features = ["defmt"] } |
| 9 | embassy-executor = { version = "0.2.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "nightly", "integrated-timers"] } | 9 | embassy-executor = { version = "0.2.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "nightly", "integrated-timers"] } |
| 10 | embassy-time = { version = "0.1.0", path = "../../../../embassy-time", features = ["nightly", "tick-hz-32_768"] } | 10 | embassy-time = { version = "0.1.2", path = "../../../../embassy-time", features = ["nightly", "tick-hz-32_768"] } |
| 11 | embassy-stm32 = { version = "0.1.0", path = "../../../../embassy-stm32", features = ["unstable-traits", "nightly", "stm32wl55jc-cm4", "time-driver-any", "exti"] } | 11 | embassy-stm32 = { version = "0.1.0", path = "../../../../embassy-stm32", features = ["unstable-traits", "nightly", "stm32wl55jc-cm4", "time-driver-any", "exti"] } |
| 12 | embassy-boot-stm32 = { version = "0.1.0", path = "../../../../embassy-boot/stm32", features = ["nightly"] } | 12 | embassy-boot-stm32 = { version = "0.1.0", path = "../../../../embassy-boot/stm32", features = ["nightly"] } |
| 13 | embassy-embedded-hal = { version = "0.1.0", path = "../../../../embassy-embedded-hal" } | 13 | embassy-embedded-hal = { version = "0.1.0", path = "../../../../embassy-embedded-hal" } |
diff --git a/examples/nrf-rtos-trace/Cargo.toml b/examples/nrf-rtos-trace/Cargo.toml index a3acc56b8..30b67b7b2 100644 --- a/examples/nrf-rtos-trace/Cargo.toml +++ b/examples/nrf-rtos-trace/Cargo.toml | |||
| @@ -18,7 +18,7 @@ log = [ | |||
| 18 | [dependencies] | 18 | [dependencies] |
| 19 | embassy-sync = { version = "0.2.0", path = "../../embassy-sync" } | 19 | embassy-sync = { version = "0.2.0", path = "../../embassy-sync" } |
| 20 | embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "rtos-trace", "rtos-trace-interrupt", "integrated-timers"] } | 20 | embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "rtos-trace", "rtos-trace-interrupt", "integrated-timers"] } |
| 21 | embassy-time = { version = "0.1.0", path = "../../embassy-time" } | 21 | embassy-time = { version = "0.1.2", path = "../../embassy-time" } |
| 22 | embassy-nrf = { version = "0.1.0", path = "../../embassy-nrf", features = ["nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac"] } | 22 | embassy-nrf = { version = "0.1.0", path = "../../embassy-nrf", features = ["nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac"] } |
| 23 | 23 | ||
| 24 | cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } | 24 | cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } |
diff --git a/examples/nrf52840-rtic/Cargo.toml b/examples/nrf52840-rtic/Cargo.toml index 0f9048b0f..ded3b7db8 100644 --- a/examples/nrf52840-rtic/Cargo.toml +++ b/examples/nrf52840-rtic/Cargo.toml | |||
| @@ -9,7 +9,7 @@ rtic = { version = "2", features = ["thumbv7-backend"] } | |||
| 9 | 9 | ||
| 10 | embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } | 10 | embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } |
| 11 | embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] } | 11 | embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] } |
| 12 | embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["nightly", "unstable-traits", "defmt", "defmt-timestamp-uptime", "generic-queue"] } | 12 | embassy-time = { version = "0.1.2", path = "../../embassy-time", features = ["nightly", "unstable-traits", "defmt", "defmt-timestamp-uptime", "generic-queue"] } |
| 13 | embassy-nrf = { version = "0.1.0", path = "../../embassy-nrf", features = ["nightly", "unstable-traits", "defmt", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } | 13 | embassy-nrf = { version = "0.1.0", path = "../../embassy-nrf", features = ["nightly", "unstable-traits", "defmt", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } |
| 14 | 14 | ||
| 15 | defmt = "0.3" | 15 | defmt = "0.3" |
diff --git a/examples/nrf52840/Cargo.toml b/examples/nrf52840/Cargo.toml index 8c4175966..7b9c371bb 100644 --- a/examples/nrf52840/Cargo.toml +++ b/examples/nrf52840/Cargo.toml | |||
| @@ -29,7 +29,7 @@ nightly = [ | |||
| 29 | embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } | 29 | embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } |
| 30 | embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] } | 30 | embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] } |
| 31 | embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] } | 31 | embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] } |
| 32 | embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } | 32 | embassy-time = { version = "0.1.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } |
| 33 | embassy-nrf = { version = "0.1.0", path = "../../embassy-nrf", features = ["defmt", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } | 33 | embassy-nrf = { version = "0.1.0", path = "../../embassy-nrf", features = ["defmt", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } |
| 34 | embassy-net = { version = "0.1.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet"], optional = true } | 34 | embassy-net = { version = "0.1.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet"], optional = true } |
| 35 | embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt", "msos-descriptor",], optional = true } | 35 | embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt", "msos-descriptor",], optional = true } |
| @@ -52,4 +52,7 @@ rand = { version = "0.8.4", default-features = false } | |||
| 52 | embedded-storage = "0.3.0" | 52 | embedded-storage = "0.3.0" |
| 53 | usbd-hid = "0.6.0" | 53 | usbd-hid = "0.6.0" |
| 54 | serde = { version = "1.0.136", default-features = false } | 54 | serde = { version = "1.0.136", default-features = false } |
| 55 | embedded-hal-async = { version = "0.2.0-alpha.1", optional = true } | 55 | embedded-hal-async = { version = "0.2.0-alpha.2", optional = true } |
| 56 | |||
| 57 | [patch.crates-io] | ||
| 58 | lora-phy = { git = "https://github.com/embassy-rs/lora-phy", rev = "ad289428fd44b02788e2fa2116445cc8f640a265" } | ||
diff --git a/examples/nrf52840/src/bin/wifi_esp_hosted.rs b/examples/nrf52840/src/bin/wifi_esp_hosted.rs index 4eb31b105..112e41bcd 100644 --- a/examples/nrf52840/src/bin/wifi_esp_hosted.rs +++ b/examples/nrf52840/src/bin/wifi_esp_hosted.rs | |||
| @@ -10,11 +10,15 @@ use embassy_nrf::gpio::{AnyPin, Input, Level, Output, OutputDrive, Pin, Pull}; | |||
| 10 | use embassy_nrf::rng::Rng; | 10 | use embassy_nrf::rng::Rng; |
| 11 | use embassy_nrf::spim::{self, Spim}; | 11 | use embassy_nrf::spim::{self, Spim}; |
| 12 | use embassy_nrf::{bind_interrupts, peripherals}; | 12 | use embassy_nrf::{bind_interrupts, peripherals}; |
| 13 | use embassy_time::Delay; | ||
| 13 | use embedded_hal_async::spi::ExclusiveDevice; | 14 | use embedded_hal_async::spi::ExclusiveDevice; |
| 14 | use embedded_io::asynch::Write; | 15 | use embedded_io::asynch::Write; |
| 15 | use static_cell::make_static; | 16 | use static_cell::make_static; |
| 16 | use {defmt_rtt as _, embassy_net_esp_hosted as hosted, panic_probe as _}; | 17 | use {defmt_rtt as _, embassy_net_esp_hosted as hosted, panic_probe as _}; |
| 17 | 18 | ||
| 19 | const WIFI_NETWORK: &str = "EmbassyTest"; | ||
| 20 | const WIFI_PASSWORD: &str = "V8YxhKt5CdIAJFud"; | ||
| 21 | |||
| 18 | bind_interrupts!(struct Irqs { | 22 | bind_interrupts!(struct Irqs { |
| 19 | SPIM3 => spim::InterruptHandler<peripherals::SPI3>; | 23 | SPIM3 => spim::InterruptHandler<peripherals::SPI3>; |
| 20 | RNG => embassy_nrf::rng::InterruptHandler<peripherals::RNG>; | 24 | RNG => embassy_nrf::rng::InterruptHandler<peripherals::RNG>; |
| @@ -24,7 +28,7 @@ bind_interrupts!(struct Irqs { | |||
| 24 | async fn wifi_task( | 28 | async fn wifi_task( |
| 25 | runner: hosted::Runner< | 29 | runner: hosted::Runner< |
| 26 | 'static, | 30 | 'static, |
| 27 | ExclusiveDevice<Spim<'static, peripherals::SPI3>, Output<'static, peripherals::P0_31>>, | 31 | ExclusiveDevice<Spim<'static, peripherals::SPI3>, Output<'static, peripherals::P0_31>, Delay>, |
| 28 | Input<'static, AnyPin>, | 32 | Input<'static, AnyPin>, |
| 29 | Output<'static, peripherals::P1_05>, | 33 | Output<'static, peripherals::P1_05>, |
| 30 | >, | 34 | >, |
| @@ -55,7 +59,7 @@ async fn main(spawner: Spawner) { | |||
| 55 | config.frequency = spim::Frequency::M32; | 59 | config.frequency = spim::Frequency::M32; |
| 56 | config.mode = spim::MODE_2; // !!! | 60 | config.mode = spim::MODE_2; // !!! |
| 57 | let spi = spim::Spim::new(p.SPI3, Irqs, sck, miso, mosi, config); | 61 | let spi = spim::Spim::new(p.SPI3, Irqs, sck, miso, mosi, config); |
| 58 | let spi = ExclusiveDevice::new(spi, cs); | 62 | let spi = ExclusiveDevice::new(spi, cs, Delay); |
| 59 | 63 | ||
| 60 | let (device, mut control, runner) = embassy_net_esp_hosted::new( | 64 | let (device, mut control, runner) = embassy_net_esp_hosted::new( |
| 61 | make_static!(embassy_net_esp_hosted::State::new()), | 65 | make_static!(embassy_net_esp_hosted::State::new()), |
| @@ -69,7 +73,7 @@ async fn main(spawner: Spawner) { | |||
| 69 | unwrap!(spawner.spawn(wifi_task(runner))); | 73 | unwrap!(spawner.spawn(wifi_task(runner))); |
| 70 | 74 | ||
| 71 | control.init().await; | 75 | control.init().await; |
| 72 | control.join(env!("WIFI_NETWORK"), env!("WIFI_PASSWORD")).await; | 76 | control.join(WIFI_NETWORK, WIFI_PASSWORD).await; |
| 73 | 77 | ||
| 74 | let config = embassy_net::Config::dhcpv4(Default::default()); | 78 | let config = embassy_net::Config::dhcpv4(Default::default()); |
| 75 | // let config = embassy_net::Config::ipv4_static(embassy_net::StaticConfigV4 { | 79 | // let config = embassy_net::Config::ipv4_static(embassy_net::StaticConfigV4 { |
diff --git a/examples/nrf5340/Cargo.toml b/examples/nrf5340/Cargo.toml index efb66bae6..f1d45f336 100644 --- a/examples/nrf5340/Cargo.toml +++ b/examples/nrf5340/Cargo.toml | |||
| @@ -14,7 +14,7 @@ embassy-executor = { version = "0.2.0", path = "../../embassy-executor", feature | |||
| 14 | "defmt", | 14 | "defmt", |
| 15 | "integrated-timers", | 15 | "integrated-timers", |
| 16 | ] } | 16 | ] } |
| 17 | embassy-time = { version = "0.1.0", path = "../../embassy-time", features = [ | 17 | embassy-time = { version = "0.1.2", path = "../../embassy-time", features = [ |
| 18 | "defmt", | 18 | "defmt", |
| 19 | "defmt-timestamp-uptime", | 19 | "defmt-timestamp-uptime", |
| 20 | ] } | 20 | ] } |
diff --git a/examples/rp/Cargo.toml b/examples/rp/Cargo.toml index 48f3a26bb..c812cb3ee 100644 --- a/examples/rp/Cargo.toml +++ b/examples/rp/Cargo.toml | |||
| @@ -9,7 +9,7 @@ license = "MIT OR Apache-2.0" | |||
| 9 | embassy-embedded-hal = { version = "0.1.0", path = "../../embassy-embedded-hal", features = ["defmt"] } | 9 | embassy-embedded-hal = { version = "0.1.0", path = "../../embassy-embedded-hal", features = ["defmt"] } |
| 10 | embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] } | 10 | embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] } |
| 11 | embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] } | 11 | embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] } |
| 12 | embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["nightly", "unstable-traits", "defmt", "defmt-timestamp-uptime"] } | 12 | embassy-time = { version = "0.1.2", path = "../../embassy-time", features = ["nightly", "unstable-traits", "defmt", "defmt-timestamp-uptime"] } |
| 13 | embassy-rp = { version = "0.1.0", path = "../../embassy-rp", features = ["defmt", "unstable-traits", "nightly", "unstable-pac", "time-driver", "critical-section-impl"] } | 13 | embassy-rp = { version = "0.1.0", path = "../../embassy-rp", features = ["defmt", "unstable-traits", "nightly", "unstable-pac", "time-driver", "critical-section-impl"] } |
| 14 | embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] } | 14 | embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] } |
| 15 | embassy-net = { version = "0.1.0", path = "../../embassy-net", features = ["defmt", "nightly", "tcp", "udp", "dhcpv4", "medium-ethernet"] } | 15 | embassy-net = { version = "0.1.0", path = "../../embassy-net", features = ["defmt", "nightly", "tcp", "udp", "dhcpv4", "medium-ethernet"] } |
| @@ -40,9 +40,10 @@ display-interface = "0.4.1" | |||
| 40 | byte-slice-cast = { version = "1.2.0", default-features = false } | 40 | byte-slice-cast = { version = "1.2.0", default-features = false } |
| 41 | smart-leds = "0.3.0" | 41 | smart-leds = "0.3.0" |
| 42 | heapless = "0.7.15" | 42 | heapless = "0.7.15" |
| 43 | usbd-hid = "0.6.1" | ||
| 43 | 44 | ||
| 44 | embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-alpha.10" } | 45 | embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-alpha.11" } |
| 45 | embedded-hal-async = "0.2.0-alpha.1" | 46 | embedded-hal-async = "0.2.0-alpha.2" |
| 46 | embedded-io = { version = "0.4.0", features = ["async", "defmt"] } | 47 | embedded-io = { version = "0.4.0", features = ["async", "defmt"] } |
| 47 | embedded-storage = { version = "0.3" } | 48 | embedded-storage = { version = "0.3" } |
| 48 | static_cell = { version = "1.1", features = ["nightly"]} | 49 | static_cell = { version = "1.1", features = ["nightly"]} |
| @@ -53,3 +54,6 @@ rand = { version = "0.8.5", default-features = false } | |||
| 53 | 54 | ||
| 54 | [profile.release] | 55 | [profile.release] |
| 55 | debug = true | 56 | debug = true |
| 57 | |||
| 58 | [patch.crates-io] | ||
| 59 | lora-phy = { git = "https://github.com/embassy-rs/lora-phy", rev = "ad289428fd44b02788e2fa2116445cc8f640a265" } | ||
diff --git a/examples/rp/src/bin/adc.rs b/examples/rp/src/bin/adc.rs index 7c2ca19f7..81a8b8340 100644 --- a/examples/rp/src/bin/adc.rs +++ b/examples/rp/src/bin/adc.rs | |||
| @@ -1,11 +1,15 @@ | |||
| 1 | //! This example test the ADC (Analog to Digital Conversion) of the RS2040 pin 26, 27 and 28. | ||
| 2 | //! It also reads the temperature sensor in the chip. | ||
| 3 | |||
| 1 | #![no_std] | 4 | #![no_std] |
| 2 | #![no_main] | 5 | #![no_main] |
| 3 | #![feature(type_alias_impl_trait)] | 6 | #![feature(type_alias_impl_trait)] |
| 4 | 7 | ||
| 5 | use defmt::*; | 8 | use defmt::*; |
| 6 | use embassy_executor::Spawner; | 9 | use embassy_executor::Spawner; |
| 7 | use embassy_rp::adc::{Adc, Config, InterruptHandler}; | 10 | use embassy_rp::adc::{Adc, Config, InterruptHandler, Pin}; |
| 8 | use embassy_rp::bind_interrupts; | 11 | use embassy_rp::bind_interrupts; |
| 12 | use embassy_rp::gpio::Pull; | ||
| 9 | use embassy_time::{Duration, Timer}; | 13 | use embassy_time::{Duration, Timer}; |
| 10 | use {defmt_rtt as _, panic_probe as _}; | 14 | use {defmt_rtt as _, panic_probe as _}; |
| 11 | 15 | ||
| @@ -18,18 +22,18 @@ async fn main(_spawner: Spawner) { | |||
| 18 | let p = embassy_rp::init(Default::default()); | 22 | let p = embassy_rp::init(Default::default()); |
| 19 | let mut adc = Adc::new(p.ADC, Irqs, Config::default()); | 23 | let mut adc = Adc::new(p.ADC, Irqs, Config::default()); |
| 20 | 24 | ||
| 21 | let mut p26 = p.PIN_26; | 25 | let mut p26 = Pin::new(p.PIN_26, Pull::None); |
| 22 | let mut p27 = p.PIN_27; | 26 | let mut p27 = Pin::new(p.PIN_27, Pull::None); |
| 23 | let mut p28 = p.PIN_28; | 27 | let mut p28 = Pin::new(p.PIN_28, Pull::None); |
| 24 | 28 | ||
| 25 | loop { | 29 | loop { |
| 26 | let level = adc.read(&mut p26).await; | 30 | let level = adc.read(&mut p26).await.unwrap(); |
| 27 | info!("Pin 26 ADC: {}", level); | 31 | info!("Pin 26 ADC: {}", level); |
| 28 | let level = adc.read(&mut p27).await; | 32 | let level = adc.read(&mut p27).await.unwrap(); |
| 29 | info!("Pin 27 ADC: {}", level); | 33 | info!("Pin 27 ADC: {}", level); |
| 30 | let level = adc.read(&mut p28).await; | 34 | let level = adc.read(&mut p28).await.unwrap(); |
| 31 | info!("Pin 28 ADC: {}", level); | 35 | info!("Pin 28 ADC: {}", level); |
| 32 | let temp = adc.read_temperature().await; | 36 | let temp = adc.read_temperature().await.unwrap(); |
| 33 | info!("Temp: {} degrees", convert_to_celsius(temp)); | 37 | info!("Temp: {} degrees", convert_to_celsius(temp)); |
| 34 | Timer::after(Duration::from_secs(1)).await; | 38 | Timer::after(Duration::from_secs(1)).await; |
| 35 | } | 39 | } |
| @@ -37,5 +41,8 @@ async fn main(_spawner: Spawner) { | |||
| 37 | 41 | ||
| 38 | fn convert_to_celsius(raw_temp: u16) -> f32 { | 42 | fn convert_to_celsius(raw_temp: u16) -> f32 { |
| 39 | // According to chapter 4.9.5. Temperature Sensor in RP2040 datasheet | 43 | // According to chapter 4.9.5. Temperature Sensor in RP2040 datasheet |
| 40 | 27.0 - (raw_temp as f32 * 3.3 / 4096.0 - 0.706) / 0.001721 as f32 | 44 | let temp = 27.0 - (raw_temp as f32 * 3.3 / 4096.0 - 0.706) / 0.001721; |
| 45 | let sign = if temp < 0.0 { -1.0 } else { 1.0 }; | ||
| 46 | let rounded_temp_x10: i16 = ((temp * 10.0) + 0.5 * sign) as i16; | ||
| 47 | (rounded_temp_x10 as f32) / 10.0 | ||
| 41 | } | 48 | } |
diff --git a/examples/rp/src/bin/blinky.rs b/examples/rp/src/bin/blinky.rs index 7aa36a19f..295b000f3 100644 --- a/examples/rp/src/bin/blinky.rs +++ b/examples/rp/src/bin/blinky.rs | |||
| @@ -1,3 +1,7 @@ | |||
| 1 | //! This example test the RP Pico on board LED. | ||
| 2 | //! | ||
| 3 | //! It does not work with the RP Pico W board. See wifi_blinky.rs. | ||
| 4 | |||
| 1 | #![no_std] | 5 | #![no_std] |
| 2 | #![no_main] | 6 | #![no_main] |
| 3 | #![feature(type_alias_impl_trait)] | 7 | #![feature(type_alias_impl_trait)] |
diff --git a/examples/rp/src/bin/button.rs b/examples/rp/src/bin/button.rs index 0d246c093..d7aa89410 100644 --- a/examples/rp/src/bin/button.rs +++ b/examples/rp/src/bin/button.rs | |||
| @@ -1,3 +1,7 @@ | |||
| 1 | //! This example uses the RP Pico on board LED to test input pin 28. This is not the button on the board. | ||
| 2 | //! | ||
| 3 | //! It does not work with the RP Pico W board. Use wifi_blinky.rs and add input pin. | ||
| 4 | |||
| 1 | #![no_std] | 5 | #![no_std] |
| 2 | #![no_main] | 6 | #![no_main] |
| 3 | #![feature(type_alias_impl_trait)] | 7 | #![feature(type_alias_impl_trait)] |
diff --git a/examples/rp/src/bin/ethernet_w5500_multisocket.rs b/examples/rp/src/bin/ethernet_w5500_multisocket.rs index 82568254a..e81da177b 100644 --- a/examples/rp/src/bin/ethernet_w5500_multisocket.rs +++ b/examples/rp/src/bin/ethernet_w5500_multisocket.rs | |||
| @@ -15,7 +15,7 @@ use embassy_rp::clocks::RoscRng; | |||
| 15 | use embassy_rp::gpio::{Input, Level, Output, Pull}; | 15 | use embassy_rp::gpio::{Input, Level, Output, Pull}; |
| 16 | use embassy_rp::peripherals::{PIN_17, PIN_20, PIN_21, SPI0}; | 16 | use embassy_rp::peripherals::{PIN_17, PIN_20, PIN_21, SPI0}; |
| 17 | use embassy_rp::spi::{Async, Config as SpiConfig, Spi}; | 17 | use embassy_rp::spi::{Async, Config as SpiConfig, Spi}; |
| 18 | use embassy_time::Duration; | 18 | use embassy_time::{Delay, Duration}; |
| 19 | use embedded_hal_async::spi::ExclusiveDevice; | 19 | use embedded_hal_async::spi::ExclusiveDevice; |
| 20 | use embedded_io::asynch::Write; | 20 | use embedded_io::asynch::Write; |
| 21 | use rand::RngCore; | 21 | use rand::RngCore; |
| @@ -26,7 +26,7 @@ use {defmt_rtt as _, panic_probe as _}; | |||
| 26 | async fn ethernet_task( | 26 | async fn ethernet_task( |
| 27 | runner: Runner< | 27 | runner: Runner< |
| 28 | 'static, | 28 | 'static, |
| 29 | ExclusiveDevice<Spi<'static, SPI0, Async>, Output<'static, PIN_17>>, | 29 | ExclusiveDevice<Spi<'static, SPI0, Async>, Output<'static, PIN_17>, Delay>, |
| 30 | Input<'static, PIN_21>, | 30 | Input<'static, PIN_21>, |
| 31 | Output<'static, PIN_20>, | 31 | Output<'static, PIN_20>, |
| 32 | >, | 32 | >, |
| @@ -54,8 +54,14 @@ async fn main(spawner: Spawner) { | |||
| 54 | 54 | ||
| 55 | let mac_addr = [0x02, 0x00, 0x00, 0x00, 0x00, 0x00]; | 55 | let mac_addr = [0x02, 0x00, 0x00, 0x00, 0x00, 0x00]; |
| 56 | let state = make_static!(State::<8, 8>::new()); | 56 | let state = make_static!(State::<8, 8>::new()); |
| 57 | let (device, runner) = | 57 | let (device, runner) = embassy_net_w5500::new( |
| 58 | embassy_net_w5500::new(mac_addr, state, ExclusiveDevice::new(spi, cs), w5500_int, w5500_reset).await; | 58 | mac_addr, |
| 59 | state, | ||
| 60 | ExclusiveDevice::new(spi, cs, Delay), | ||
| 61 | w5500_int, | ||
| 62 | w5500_reset, | ||
| 63 | ) | ||
| 64 | .await; | ||
| 59 | unwrap!(spawner.spawn(ethernet_task(runner))); | 65 | unwrap!(spawner.spawn(ethernet_task(runner))); |
| 60 | 66 | ||
| 61 | // Generate random seed | 67 | // Generate random seed |
diff --git a/examples/rp/src/bin/ethernet_w5500_tcp_client.rs b/examples/rp/src/bin/ethernet_w5500_tcp_client.rs index d562defad..9dd7ae973 100644 --- a/examples/rp/src/bin/ethernet_w5500_tcp_client.rs +++ b/examples/rp/src/bin/ethernet_w5500_tcp_client.rs | |||
| @@ -17,7 +17,7 @@ use embassy_rp::clocks::RoscRng; | |||
| 17 | use embassy_rp::gpio::{Input, Level, Output, Pull}; | 17 | use embassy_rp::gpio::{Input, Level, Output, Pull}; |
| 18 | use embassy_rp::peripherals::{PIN_17, PIN_20, PIN_21, SPI0}; | 18 | use embassy_rp::peripherals::{PIN_17, PIN_20, PIN_21, SPI0}; |
| 19 | use embassy_rp::spi::{Async, Config as SpiConfig, Spi}; | 19 | use embassy_rp::spi::{Async, Config as SpiConfig, Spi}; |
| 20 | use embassy_time::{Duration, Timer}; | 20 | use embassy_time::{Delay, Duration, Timer}; |
| 21 | use embedded_hal_async::spi::ExclusiveDevice; | 21 | use embedded_hal_async::spi::ExclusiveDevice; |
| 22 | use embedded_io::asynch::Write; | 22 | use embedded_io::asynch::Write; |
| 23 | use rand::RngCore; | 23 | use rand::RngCore; |
| @@ -28,7 +28,7 @@ use {defmt_rtt as _, panic_probe as _}; | |||
| 28 | async fn ethernet_task( | 28 | async fn ethernet_task( |
| 29 | runner: Runner< | 29 | runner: Runner< |
| 30 | 'static, | 30 | 'static, |
| 31 | ExclusiveDevice<Spi<'static, SPI0, Async>, Output<'static, PIN_17>>, | 31 | ExclusiveDevice<Spi<'static, SPI0, Async>, Output<'static, PIN_17>, Delay>, |
| 32 | Input<'static, PIN_21>, | 32 | Input<'static, PIN_21>, |
| 33 | Output<'static, PIN_20>, | 33 | Output<'static, PIN_20>, |
| 34 | >, | 34 | >, |
| @@ -57,8 +57,14 @@ async fn main(spawner: Spawner) { | |||
| 57 | 57 | ||
| 58 | let mac_addr = [0x02, 0x00, 0x00, 0x00, 0x00, 0x00]; | 58 | let mac_addr = [0x02, 0x00, 0x00, 0x00, 0x00, 0x00]; |
| 59 | let state = make_static!(State::<8, 8>::new()); | 59 | let state = make_static!(State::<8, 8>::new()); |
| 60 | let (device, runner) = | 60 | let (device, runner) = embassy_net_w5500::new( |
| 61 | embassy_net_w5500::new(mac_addr, state, ExclusiveDevice::new(spi, cs), w5500_int, w5500_reset).await; | 61 | mac_addr, |
| 62 | state, | ||
| 63 | ExclusiveDevice::new(spi, cs, Delay), | ||
| 64 | w5500_int, | ||
| 65 | w5500_reset, | ||
| 66 | ) | ||
| 67 | .await; | ||
| 62 | unwrap!(spawner.spawn(ethernet_task(runner))); | 68 | unwrap!(spawner.spawn(ethernet_task(runner))); |
| 63 | 69 | ||
| 64 | // Generate random seed | 70 | // Generate random seed |
diff --git a/examples/rp/src/bin/ethernet_w5500_tcp_server.rs b/examples/rp/src/bin/ethernet_w5500_tcp_server.rs index 7f521cdb4..db21c2b6f 100644 --- a/examples/rp/src/bin/ethernet_w5500_tcp_server.rs +++ b/examples/rp/src/bin/ethernet_w5500_tcp_server.rs | |||
| @@ -16,7 +16,7 @@ use embassy_rp::clocks::RoscRng; | |||
| 16 | use embassy_rp::gpio::{Input, Level, Output, Pull}; | 16 | use embassy_rp::gpio::{Input, Level, Output, Pull}; |
| 17 | use embassy_rp::peripherals::{PIN_17, PIN_20, PIN_21, SPI0}; | 17 | use embassy_rp::peripherals::{PIN_17, PIN_20, PIN_21, SPI0}; |
| 18 | use embassy_rp::spi::{Async, Config as SpiConfig, Spi}; | 18 | use embassy_rp::spi::{Async, Config as SpiConfig, Spi}; |
| 19 | use embassy_time::Duration; | 19 | use embassy_time::{Delay, Duration}; |
| 20 | use embedded_hal_async::spi::ExclusiveDevice; | 20 | use embedded_hal_async::spi::ExclusiveDevice; |
| 21 | use embedded_io::asynch::Write; | 21 | use embedded_io::asynch::Write; |
| 22 | use rand::RngCore; | 22 | use rand::RngCore; |
| @@ -26,7 +26,7 @@ use {defmt_rtt as _, panic_probe as _}; | |||
| 26 | async fn ethernet_task( | 26 | async fn ethernet_task( |
| 27 | runner: Runner< | 27 | runner: Runner< |
| 28 | 'static, | 28 | 'static, |
| 29 | ExclusiveDevice<Spi<'static, SPI0, Async>, Output<'static, PIN_17>>, | 29 | ExclusiveDevice<Spi<'static, SPI0, Async>, Output<'static, PIN_17>, Delay>, |
| 30 | Input<'static, PIN_21>, | 30 | Input<'static, PIN_21>, |
| 31 | Output<'static, PIN_20>, | 31 | Output<'static, PIN_20>, |
| 32 | >, | 32 | >, |
| @@ -55,8 +55,14 @@ async fn main(spawner: Spawner) { | |||
| 55 | 55 | ||
| 56 | let mac_addr = [0x02, 0x00, 0x00, 0x00, 0x00, 0x00]; | 56 | let mac_addr = [0x02, 0x00, 0x00, 0x00, 0x00, 0x00]; |
| 57 | let state = make_static!(State::<8, 8>::new()); | 57 | let state = make_static!(State::<8, 8>::new()); |
| 58 | let (device, runner) = | 58 | let (device, runner) = embassy_net_w5500::new( |
| 59 | embassy_net_w5500::new(mac_addr, state, ExclusiveDevice::new(spi, cs), w5500_int, w5500_reset).await; | 59 | mac_addr, |
| 60 | state, | ||
| 61 | ExclusiveDevice::new(spi, cs, Delay), | ||
| 62 | w5500_int, | ||
| 63 | w5500_reset, | ||
| 64 | ) | ||
| 65 | .await; | ||
| 60 | unwrap!(spawner.spawn(ethernet_task(runner))); | 66 | unwrap!(spawner.spawn(ethernet_task(runner))); |
| 61 | 67 | ||
| 62 | // Generate random seed | 68 | // Generate random seed |
diff --git a/examples/rp/src/bin/ethernet_w5500_udp.rs b/examples/rp/src/bin/ethernet_w5500_udp.rs index ada86ae55..038432b17 100644 --- a/examples/rp/src/bin/ethernet_w5500_udp.rs +++ b/examples/rp/src/bin/ethernet_w5500_udp.rs | |||
| @@ -16,6 +16,7 @@ use embassy_rp::clocks::RoscRng; | |||
| 16 | use embassy_rp::gpio::{Input, Level, Output, Pull}; | 16 | use embassy_rp::gpio::{Input, Level, Output, Pull}; |
| 17 | use embassy_rp::peripherals::{PIN_17, PIN_20, PIN_21, SPI0}; | 17 | use embassy_rp::peripherals::{PIN_17, PIN_20, PIN_21, SPI0}; |
| 18 | use embassy_rp::spi::{Async, Config as SpiConfig, Spi}; | 18 | use embassy_rp::spi::{Async, Config as SpiConfig, Spi}; |
| 19 | use embassy_time::Delay; | ||
| 19 | use embedded_hal_async::spi::ExclusiveDevice; | 20 | use embedded_hal_async::spi::ExclusiveDevice; |
| 20 | use rand::RngCore; | 21 | use rand::RngCore; |
| 21 | use static_cell::make_static; | 22 | use static_cell::make_static; |
| @@ -24,7 +25,7 @@ use {defmt_rtt as _, panic_probe as _}; | |||
| 24 | async fn ethernet_task( | 25 | async fn ethernet_task( |
| 25 | runner: Runner< | 26 | runner: Runner< |
| 26 | 'static, | 27 | 'static, |
| 27 | ExclusiveDevice<Spi<'static, SPI0, Async>, Output<'static, PIN_17>>, | 28 | ExclusiveDevice<Spi<'static, SPI0, Async>, Output<'static, PIN_17>, Delay>, |
| 28 | Input<'static, PIN_21>, | 29 | Input<'static, PIN_21>, |
| 29 | Output<'static, PIN_20>, | 30 | Output<'static, PIN_20>, |
| 30 | >, | 31 | >, |
| @@ -52,8 +53,14 @@ async fn main(spawner: Spawner) { | |||
| 52 | 53 | ||
| 53 | let mac_addr = [0x02, 0x00, 0x00, 0x00, 0x00, 0x00]; | 54 | let mac_addr = [0x02, 0x00, 0x00, 0x00, 0x00, 0x00]; |
| 54 | let state = make_static!(State::<8, 8>::new()); | 55 | let state = make_static!(State::<8, 8>::new()); |
| 55 | let (device, runner) = | 56 | let (device, runner) = embassy_net_w5500::new( |
| 56 | embassy_net_w5500::new(mac_addr, state, ExclusiveDevice::new(spi, cs), w5500_int, w5500_reset).await; | 57 | mac_addr, |
| 58 | state, | ||
| 59 | ExclusiveDevice::new(spi, cs, Delay), | ||
| 60 | w5500_int, | ||
| 61 | w5500_reset, | ||
| 62 | ) | ||
| 63 | .await; | ||
| 57 | unwrap!(spawner.spawn(ethernet_task(runner))); | 64 | unwrap!(spawner.spawn(ethernet_task(runner))); |
| 58 | 65 | ||
| 59 | // Generate random seed | 66 | // Generate random seed |
diff --git a/examples/rp/src/bin/flash.rs b/examples/rp/src/bin/flash.rs index 19076150c..4c4982acc 100644 --- a/examples/rp/src/bin/flash.rs +++ b/examples/rp/src/bin/flash.rs | |||
| @@ -1,3 +1,5 @@ | |||
| 1 | //! This example test the flash connected to the RP2040 chip. | ||
| 2 | |||
| 1 | #![no_std] | 3 | #![no_std] |
| 2 | #![no_main] | 4 | #![no_main] |
| 3 | #![feature(type_alias_impl_trait)] | 5 | #![feature(type_alias_impl_trait)] |
diff --git a/examples/rp/src/bin/gpio_async.rs b/examples/rp/src/bin/gpio_async.rs index 52d13a9d5..bf58044d5 100644 --- a/examples/rp/src/bin/gpio_async.rs +++ b/examples/rp/src/bin/gpio_async.rs | |||
| @@ -1,3 +1,7 @@ | |||
| 1 | //! This example shows how async gpio can be used with a RP2040. | ||
| 2 | //! | ||
| 3 | //! The LED on the RP Pico W board is connected differently. See wifi_blinky.rs. | ||
| 4 | |||
| 1 | #![no_std] | 5 | #![no_std] |
| 2 | #![no_main] | 6 | #![no_main] |
| 3 | #![feature(type_alias_impl_trait)] | 7 | #![feature(type_alias_impl_trait)] |
| @@ -9,8 +13,6 @@ use embassy_time::{Duration, Timer}; | |||
| 9 | use gpio::{Input, Level, Output, Pull}; | 13 | use gpio::{Input, Level, Output, Pull}; |
| 10 | use {defmt_rtt as _, panic_probe as _}; | 14 | use {defmt_rtt as _, panic_probe as _}; |
| 11 | 15 | ||
| 12 | /// This example shows how async gpio can be used with a RP2040. | ||
| 13 | /// | ||
| 14 | /// It requires an external signal to be manually triggered on PIN 16. For | 16 | /// It requires an external signal to be manually triggered on PIN 16. For |
| 15 | /// example, this could be accomplished using an external power source with a | 17 | /// example, this could be accomplished using an external power source with a |
| 16 | /// button so that it is possible to toggle the signal from low to high. | 18 | /// button so that it is possible to toggle the signal from low to high. |
diff --git a/examples/rp/src/bin/gpout.rs b/examples/rp/src/bin/gpout.rs index 64461fc5f..0a3b5fa98 100644 --- a/examples/rp/src/bin/gpout.rs +++ b/examples/rp/src/bin/gpout.rs | |||
| @@ -1,3 +1,7 @@ | |||
| 1 | //! This example shows how GPOUT (General purpose clock outputs) can toggle a output pin. | ||
| 2 | //! | ||
| 3 | //! The LED on the RP Pico W board is connected differently. Add a LED and resistor to another pin. | ||
| 4 | |||
| 1 | #![no_std] | 5 | #![no_std] |
| 2 | #![no_main] | 6 | #![no_main] |
| 3 | #![feature(type_alias_impl_trait)] | 7 | #![feature(type_alias_impl_trait)] |
diff --git a/examples/rp/src/bin/i2c_async.rs b/examples/rp/src/bin/i2c_async.rs index cf3cf742c..93224bc43 100644 --- a/examples/rp/src/bin/i2c_async.rs +++ b/examples/rp/src/bin/i2c_async.rs | |||
| @@ -1,3 +1,8 @@ | |||
| 1 | //! This example shows how to communicate asynchronous using i2c with external chips. | ||
| 2 | //! | ||
| 3 | //! Example written for the [`MCP23017 16-Bit I2C I/O Expander with Serial Interface`] chip. | ||
| 4 | //! (https://www.microchip.com/en-us/product/mcp23017) | ||
| 5 | |||
| 1 | #![no_std] | 6 | #![no_std] |
| 2 | #![no_main] | 7 | #![no_main] |
| 3 | #![feature(type_alias_impl_trait)] | 8 | #![feature(type_alias_impl_trait)] |
diff --git a/examples/rp/src/bin/i2c_blocking.rs b/examples/rp/src/bin/i2c_blocking.rs index 7623e33c8..1c8c2039d 100644 --- a/examples/rp/src/bin/i2c_blocking.rs +++ b/examples/rp/src/bin/i2c_blocking.rs | |||
| @@ -1,3 +1,8 @@ | |||
| 1 | //! This example shows how to communicate using i2c with external chips. | ||
| 2 | //! | ||
| 3 | //! Example written for the [`MCP23017 16-Bit I2C I/O Expander with Serial Interface`] chip. | ||
| 4 | //! (https://www.microchip.com/en-us/product/mcp23017) | ||
| 5 | |||
| 1 | #![no_std] | 6 | #![no_std] |
| 2 | #![no_main] | 7 | #![no_main] |
| 3 | #![feature(type_alias_impl_trait)] | 8 | #![feature(type_alias_impl_trait)] |
diff --git a/examples/rp/src/bin/lora_lorawan.rs b/examples/rp/src/bin/lora_lorawan.rs index a9c84bf95..d631fafa1 100644 --- a/examples/rp/src/bin/lora_lorawan.rs +++ b/examples/rp/src/bin/lora_lorawan.rs | |||
| @@ -1,5 +1,6 @@ | |||
| 1 | //! This example runs on the Raspberry Pi Pico with a Waveshare board containing a Semtech Sx1262 radio. | 1 | //! This example runs on the Raspberry Pi Pico with a Waveshare board containing a Semtech Sx1262 radio. |
| 2 | //! It demonstrates LoRaWAN join functionality. | 2 | //! It demonstrates LoRaWAN join functionality. |
| 3 | |||
| 3 | #![no_std] | 4 | #![no_std] |
| 4 | #![no_main] | 5 | #![no_main] |
| 5 | #![macro_use] | 6 | #![macro_use] |
diff --git a/examples/rp/src/bin/lora_p2p_receive.rs b/examples/rp/src/bin/lora_p2p_receive.rs index 250419202..396d669de 100644 --- a/examples/rp/src/bin/lora_p2p_receive.rs +++ b/examples/rp/src/bin/lora_p2p_receive.rs | |||
| @@ -1,5 +1,6 @@ | |||
| 1 | //! This example runs on the Raspberry Pi Pico with a Waveshare board containing a Semtech Sx1262 radio. | 1 | //! This example runs on the Raspberry Pi Pico with a Waveshare board containing a Semtech Sx1262 radio. |
| 2 | //! It demonstrates LORA P2P receive functionality in conjunction with the lora_p2p_send example. | 2 | //! It demonstrates LORA P2P receive functionality in conjunction with the lora_p2p_send example. |
| 3 | |||
| 3 | #![no_std] | 4 | #![no_std] |
| 4 | #![no_main] | 5 | #![no_main] |
| 5 | #![macro_use] | 6 | #![macro_use] |
diff --git a/examples/rp/src/bin/lora_p2p_send.rs b/examples/rp/src/bin/lora_p2p_send.rs index 3a0544b17..a0f70fa5c 100644 --- a/examples/rp/src/bin/lora_p2p_send.rs +++ b/examples/rp/src/bin/lora_p2p_send.rs | |||
| @@ -1,5 +1,6 @@ | |||
| 1 | //! This example runs on the Raspberry Pi Pico with a Waveshare board containing a Semtech Sx1262 radio. | 1 | //! This example runs on the Raspberry Pi Pico with a Waveshare board containing a Semtech Sx1262 radio. |
| 2 | //! It demonstrates LORA P2P send functionality. | 2 | //! It demonstrates LORA P2P send functionality. |
| 3 | |||
| 3 | #![no_std] | 4 | #![no_std] |
| 4 | #![no_main] | 5 | #![no_main] |
| 5 | #![macro_use] | 6 | #![macro_use] |
diff --git a/examples/rp/src/bin/lora_p2p_send_multicore.rs b/examples/rp/src/bin/lora_p2p_send_multicore.rs index eef2f7a53..89a62818d 100644 --- a/examples/rp/src/bin/lora_p2p_send_multicore.rs +++ b/examples/rp/src/bin/lora_p2p_send_multicore.rs | |||
| @@ -1,5 +1,6 @@ | |||
| 1 | //! This example runs on the Raspberry Pi Pico with a Waveshare board containing a Semtech Sx1262 radio. | 1 | //! This example runs on the Raspberry Pi Pico with a Waveshare board containing a Semtech Sx1262 radio. |
| 2 | //! It demonstrates LORA P2P send functionality using the second core, with data provided by the first core. | 2 | //! It demonstrates LORA P2P send functionality using the second core, with data provided by the first core. |
| 3 | |||
| 3 | #![no_std] | 4 | #![no_std] |
| 4 | #![no_main] | 5 | #![no_main] |
| 5 | #![macro_use] | 6 | #![macro_use] |
diff --git a/examples/rp/src/bin/multicore.rs b/examples/rp/src/bin/multicore.rs index 57278dd6c..893b724bf 100644 --- a/examples/rp/src/bin/multicore.rs +++ b/examples/rp/src/bin/multicore.rs | |||
| @@ -1,3 +1,7 @@ | |||
| 1 | //! This example shows how to send messages between the two cores in the RP2040 chip. | ||
| 2 | //! | ||
| 3 | //! The LED on the RP Pico W board is connected differently. See wifi_blinky.rs. | ||
| 4 | |||
| 1 | #![no_std] | 5 | #![no_std] |
| 2 | #![no_main] | 6 | #![no_main] |
| 3 | #![feature(type_alias_impl_trait)] | 7 | #![feature(type_alias_impl_trait)] |
diff --git a/examples/rp/src/bin/pio_async.rs b/examples/rp/src/bin/pio_async.rs index 79eda1a09..c001d6440 100644 --- a/examples/rp/src/bin/pio_async.rs +++ b/examples/rp/src/bin/pio_async.rs | |||
| @@ -1,15 +1,22 @@ | |||
| 1 | //! This example shows powerful PIO module in the RP2040 chip. | ||
| 2 | |||
| 1 | #![no_std] | 3 | #![no_std] |
| 2 | #![no_main] | 4 | #![no_main] |
| 3 | #![feature(type_alias_impl_trait)] | 5 | #![feature(type_alias_impl_trait)] |
| 4 | use defmt::info; | 6 | use defmt::info; |
| 5 | use embassy_executor::Spawner; | 7 | use embassy_executor::Spawner; |
| 8 | use embassy_rp::bind_interrupts; | ||
| 6 | use embassy_rp::peripherals::PIO0; | 9 | use embassy_rp::peripherals::PIO0; |
| 7 | use embassy_rp::pio::{Common, Config, Irq, Pio, PioPin, ShiftDirection, StateMachine}; | 10 | use embassy_rp::pio::{Common, Config, InterruptHandler, Irq, Pio, PioPin, ShiftDirection, StateMachine}; |
| 8 | use embassy_rp::relocate::RelocatedProgram; | 11 | use embassy_rp::relocate::RelocatedProgram; |
| 9 | use fixed::traits::ToFixed; | 12 | use fixed::traits::ToFixed; |
| 10 | use fixed_macro::types::U56F8; | 13 | use fixed_macro::types::U56F8; |
| 11 | use {defmt_rtt as _, panic_probe as _}; | 14 | use {defmt_rtt as _, panic_probe as _}; |
| 12 | 15 | ||
| 16 | bind_interrupts!(struct Irqs { | ||
| 17 | PIO0_IRQ_0 => InterruptHandler<PIO0>; | ||
| 18 | }); | ||
| 19 | |||
| 13 | fn setup_pio_task_sm0<'a>(pio: &mut Common<'a, PIO0>, sm: &mut StateMachine<'a, PIO0, 0>, pin: impl PioPin) { | 20 | fn setup_pio_task_sm0<'a>(pio: &mut Common<'a, PIO0>, sm: &mut StateMachine<'a, PIO0, 0>, pin: impl PioPin) { |
| 14 | // Setup sm0 | 21 | // Setup sm0 |
| 15 | 22 | ||
| @@ -49,7 +56,14 @@ fn setup_pio_task_sm1<'a>(pio: &mut Common<'a, PIO0>, sm: &mut StateMachine<'a, | |||
| 49 | // Setupm sm1 | 56 | // Setupm sm1 |
| 50 | 57 | ||
| 51 | // Read 0b10101 repeatedly until ISR is full | 58 | // Read 0b10101 repeatedly until ISR is full |
| 52 | let prg = pio_proc::pio_asm!(".origin 8", "set x, 0x15", ".wrap_target", "in x, 5 [31]", ".wrap",); | 59 | let prg = pio_proc::pio_asm!( |
| 60 | // | ||
| 61 | ".origin 8", | ||
| 62 | "set x, 0x15", | ||
| 63 | ".wrap_target", | ||
| 64 | "in x, 5 [31]", | ||
| 65 | ".wrap", | ||
| 66 | ); | ||
| 53 | 67 | ||
| 54 | let relocated = RelocatedProgram::new(&prg.program); | 68 | let relocated = RelocatedProgram::new(&prg.program); |
| 55 | let mut cfg = Config::default(); | 69 | let mut cfg = Config::default(); |
| @@ -110,7 +124,7 @@ async fn main(spawner: Spawner) { | |||
| 110 | mut sm1, | 124 | mut sm1, |
| 111 | mut sm2, | 125 | mut sm2, |
| 112 | .. | 126 | .. |
| 113 | } = Pio::new(pio); | 127 | } = Pio::new(pio, Irqs); |
| 114 | 128 | ||
| 115 | setup_pio_task_sm0(&mut common, &mut sm0, p.PIN_0); | 129 | setup_pio_task_sm0(&mut common, &mut sm0, p.PIN_0); |
| 116 | setup_pio_task_sm1(&mut common, &mut sm1); | 130 | setup_pio_task_sm1(&mut common, &mut sm1); |
diff --git a/examples/rp/src/bin/pio_dma.rs b/examples/rp/src/bin/pio_dma.rs index 05c0ebb16..9ab72e1f3 100644 --- a/examples/rp/src/bin/pio_dma.rs +++ b/examples/rp/src/bin/pio_dma.rs | |||
| @@ -1,16 +1,23 @@ | |||
| 1 | //! This example shows powerful PIO module in the RP2040 chip. | ||
| 2 | |||
| 1 | #![no_std] | 3 | #![no_std] |
| 2 | #![no_main] | 4 | #![no_main] |
| 3 | #![feature(type_alias_impl_trait)] | 5 | #![feature(type_alias_impl_trait)] |
| 4 | use defmt::info; | 6 | use defmt::info; |
| 5 | use embassy_executor::Spawner; | 7 | use embassy_executor::Spawner; |
| 6 | use embassy_futures::join::join; | 8 | use embassy_futures::join::join; |
| 7 | use embassy_rp::pio::{Config, Pio, ShiftConfig, ShiftDirection}; | 9 | use embassy_rp::peripherals::PIO0; |
| 10 | use embassy_rp::pio::{Config, InterruptHandler, Pio, ShiftConfig, ShiftDirection}; | ||
| 8 | use embassy_rp::relocate::RelocatedProgram; | 11 | use embassy_rp::relocate::RelocatedProgram; |
| 9 | use embassy_rp::Peripheral; | 12 | use embassy_rp::{bind_interrupts, Peripheral}; |
| 10 | use fixed::traits::ToFixed; | 13 | use fixed::traits::ToFixed; |
| 11 | use fixed_macro::types::U56F8; | 14 | use fixed_macro::types::U56F8; |
| 12 | use {defmt_rtt as _, panic_probe as _}; | 15 | use {defmt_rtt as _, panic_probe as _}; |
| 13 | 16 | ||
| 17 | bind_interrupts!(struct Irqs { | ||
| 18 | PIO0_IRQ_0 => InterruptHandler<PIO0>; | ||
| 19 | }); | ||
| 20 | |||
| 14 | fn swap_nibbles(v: u32) -> u32 { | 21 | fn swap_nibbles(v: u32) -> u32 { |
| 15 | let v = (v & 0x0f0f_0f0f) << 4 | (v & 0xf0f0_f0f0) >> 4; | 22 | let v = (v & 0x0f0f_0f0f) << 4 | (v & 0xf0f0_f0f0) >> 4; |
| 16 | let v = (v & 0x00ff_00ff) << 8 | (v & 0xff00_ff00) >> 8; | 23 | let v = (v & 0x00ff_00ff) << 8 | (v & 0xff00_ff00) >> 8; |
| @@ -25,7 +32,7 @@ async fn main(_spawner: Spawner) { | |||
| 25 | mut common, | 32 | mut common, |
| 26 | sm0: mut sm, | 33 | sm0: mut sm, |
| 27 | .. | 34 | .. |
| 28 | } = Pio::new(pio); | 35 | } = Pio::new(pio, Irqs); |
| 29 | 36 | ||
| 30 | let prg = pio_proc::pio_asm!( | 37 | let prg = pio_proc::pio_asm!( |
| 31 | ".origin 0", | 38 | ".origin 0", |
diff --git a/examples/rp/src/bin/pio_hd44780.rs b/examples/rp/src/bin/pio_hd44780.rs index bfc6c9908..8aedd24b6 100644 --- a/examples/rp/src/bin/pio_hd44780.rs +++ b/examples/rp/src/bin/pio_hd44780.rs | |||
| @@ -1,3 +1,6 @@ | |||
| 1 | //! This example shows powerful PIO module in the RP2040 chip to communicate with a HD44780 display. | ||
| 2 | //! See (https://www.sparkfun.com/datasheets/LCD/HD44780.pdf) | ||
| 3 | |||
| 1 | #![no_std] | 4 | #![no_std] |
| 2 | #![no_main] | 5 | #![no_main] |
| 3 | #![feature(type_alias_impl_trait)] | 6 | #![feature(type_alias_impl_trait)] |
| @@ -7,13 +10,19 @@ use core::fmt::Write; | |||
| 7 | use embassy_executor::Spawner; | 10 | use embassy_executor::Spawner; |
| 8 | use embassy_rp::dma::{AnyChannel, Channel}; | 11 | use embassy_rp::dma::{AnyChannel, Channel}; |
| 9 | use embassy_rp::peripherals::PIO0; | 12 | use embassy_rp::peripherals::PIO0; |
| 10 | use embassy_rp::pio::{Config, Direction, FifoJoin, Pio, PioPin, ShiftConfig, ShiftDirection, StateMachine}; | 13 | use embassy_rp::pio::{ |
| 14 | Config, Direction, FifoJoin, InterruptHandler, Pio, PioPin, ShiftConfig, ShiftDirection, StateMachine, | ||
| 15 | }; | ||
| 11 | use embassy_rp::pwm::{self, Pwm}; | 16 | use embassy_rp::pwm::{self, Pwm}; |
| 12 | use embassy_rp::relocate::RelocatedProgram; | 17 | use embassy_rp::relocate::RelocatedProgram; |
| 13 | use embassy_rp::{into_ref, Peripheral, PeripheralRef}; | 18 | use embassy_rp::{bind_interrupts, into_ref, Peripheral, PeripheralRef}; |
| 14 | use embassy_time::{Duration, Instant, Timer}; | 19 | use embassy_time::{Duration, Instant, Timer}; |
| 15 | use {defmt_rtt as _, panic_probe as _}; | 20 | use {defmt_rtt as _, panic_probe as _}; |
| 16 | 21 | ||
| 22 | bind_interrupts!(pub struct Irqs { | ||
| 23 | PIO0_IRQ_0 => InterruptHandler<PIO0>; | ||
| 24 | }); | ||
| 25 | |||
| 17 | #[embassy_executor::main] | 26 | #[embassy_executor::main] |
| 18 | async fn main(_spawner: Spawner) { | 27 | async fn main(_spawner: Spawner) { |
| 19 | // this test assumes a 2x16 HD44780 display attached as follow: | 28 | // this test assumes a 2x16 HD44780 display attached as follow: |
| @@ -37,7 +46,7 @@ async fn main(_spawner: Spawner) { | |||
| 37 | }); | 46 | }); |
| 38 | 47 | ||
| 39 | let mut hd = HD44780::new( | 48 | let mut hd = HD44780::new( |
| 40 | p.PIO0, p.DMA_CH3, p.PIN_0, p.PIN_1, p.PIN_2, p.PIN_3, p.PIN_4, p.PIN_5, p.PIN_6, | 49 | p.PIO0, Irqs, p.DMA_CH3, p.PIN_0, p.PIN_1, p.PIN_2, p.PIN_3, p.PIN_4, p.PIN_5, p.PIN_6, |
| 41 | ) | 50 | ) |
| 42 | .await; | 51 | .await; |
| 43 | 52 | ||
| @@ -72,6 +81,7 @@ pub struct HD44780<'l> { | |||
| 72 | impl<'l> HD44780<'l> { | 81 | impl<'l> HD44780<'l> { |
| 73 | pub async fn new( | 82 | pub async fn new( |
| 74 | pio: impl Peripheral<P = PIO0> + 'l, | 83 | pio: impl Peripheral<P = PIO0> + 'l, |
| 84 | irq: Irqs, | ||
| 75 | dma: impl Peripheral<P = impl Channel> + 'l, | 85 | dma: impl Peripheral<P = impl Channel> + 'l, |
| 76 | rs: impl PioPin, | 86 | rs: impl PioPin, |
| 77 | rw: impl PioPin, | 87 | rw: impl PioPin, |
| @@ -88,7 +98,7 @@ impl<'l> HD44780<'l> { | |||
| 88 | mut irq0, | 98 | mut irq0, |
| 89 | mut sm0, | 99 | mut sm0, |
| 90 | .. | 100 | .. |
| 91 | } = Pio::new(pio); | 101 | } = Pio::new(pio, irq); |
| 92 | 102 | ||
| 93 | // takes command words (<wait:24> <command:4> <0:4>) | 103 | // takes command words (<wait:24> <command:4> <0:4>) |
| 94 | let prg = pio_proc::pio_asm!( | 104 | let prg = pio_proc::pio_asm!( |
diff --git a/examples/rp/src/bin/pio_ws2812.rs b/examples/rp/src/bin/pio_ws2812.rs index 26422421f..3de2bd48d 100644 --- a/examples/rp/src/bin/pio_ws2812.rs +++ b/examples/rp/src/bin/pio_ws2812.rs | |||
| @@ -1,3 +1,6 @@ | |||
| 1 | //! This example shows powerful PIO module in the RP2040 chip to communicate with WS2812 LED modules. | ||
| 2 | //! See (https://www.sparkfun.com/categories/tags/ws2812) | ||
| 3 | |||
| 1 | #![no_std] | 4 | #![no_std] |
| 2 | #![no_main] | 5 | #![no_main] |
| 3 | #![feature(type_alias_impl_trait)] | 6 | #![feature(type_alias_impl_trait)] |
| @@ -5,15 +8,22 @@ | |||
| 5 | use defmt::*; | 8 | use defmt::*; |
| 6 | use embassy_executor::Spawner; | 9 | use embassy_executor::Spawner; |
| 7 | use embassy_rp::dma::{AnyChannel, Channel}; | 10 | use embassy_rp::dma::{AnyChannel, Channel}; |
| 8 | use embassy_rp::pio::{Common, Config, FifoJoin, Instance, Pio, PioPin, ShiftConfig, ShiftDirection, StateMachine}; | 11 | use embassy_rp::peripherals::PIO0; |
| 12 | use embassy_rp::pio::{ | ||
| 13 | Common, Config, FifoJoin, Instance, InterruptHandler, Pio, PioPin, ShiftConfig, ShiftDirection, StateMachine, | ||
| 14 | }; | ||
| 9 | use embassy_rp::relocate::RelocatedProgram; | 15 | use embassy_rp::relocate::RelocatedProgram; |
| 10 | use embassy_rp::{clocks, into_ref, Peripheral, PeripheralRef}; | 16 | use embassy_rp::{bind_interrupts, clocks, into_ref, Peripheral, PeripheralRef}; |
| 11 | use embassy_time::{Duration, Timer}; | 17 | use embassy_time::{Duration, Timer}; |
| 12 | use fixed::types::U24F8; | 18 | use fixed::types::U24F8; |
| 13 | use fixed_macro::fixed; | 19 | use fixed_macro::fixed; |
| 14 | use smart_leds::RGB8; | 20 | use smart_leds::RGB8; |
| 15 | use {defmt_rtt as _, panic_probe as _}; | 21 | use {defmt_rtt as _, panic_probe as _}; |
| 16 | 22 | ||
| 23 | bind_interrupts!(struct Irqs { | ||
| 24 | PIO0_IRQ_0 => InterruptHandler<PIO0>; | ||
| 25 | }); | ||
| 26 | |||
| 17 | pub struct Ws2812<'d, P: Instance, const S: usize, const N: usize> { | 27 | pub struct Ws2812<'d, P: Instance, const S: usize, const N: usize> { |
| 18 | dma: PeripheralRef<'d, AnyChannel>, | 28 | dma: PeripheralRef<'d, AnyChannel>, |
| 19 | sm: StateMachine<'d, P, S>, | 29 | sm: StateMachine<'d, P, S>, |
| @@ -123,7 +133,7 @@ async fn main(_spawner: Spawner) { | |||
| 123 | info!("Start"); | 133 | info!("Start"); |
| 124 | let p = embassy_rp::init(Default::default()); | 134 | let p = embassy_rp::init(Default::default()); |
| 125 | 135 | ||
| 126 | let Pio { mut common, sm0, .. } = Pio::new(p.PIO0); | 136 | let Pio { mut common, sm0, .. } = Pio::new(p.PIO0, Irqs); |
| 127 | 137 | ||
| 128 | // This is the number of leds in the string. Helpfully, the sparkfun thing plus and adafruit | 138 | // This is the number of leds in the string. Helpfully, the sparkfun thing plus and adafruit |
| 129 | // feather boards for the 2040 both have one built in. | 139 | // feather boards for the 2040 both have one built in. |
diff --git a/examples/rp/src/bin/pwm.rs b/examples/rp/src/bin/pwm.rs index 2b3d5d97a..9d919287c 100644 --- a/examples/rp/src/bin/pwm.rs +++ b/examples/rp/src/bin/pwm.rs | |||
| @@ -1,3 +1,7 @@ | |||
| 1 | //! This example shows how to use PWM (Pulse Width Modulation) in the RP2040 chip. | ||
| 2 | //! | ||
| 3 | //! The LED on the RP Pico W board is connected differently. Add a LED and resistor to another pin. | ||
| 4 | |||
| 1 | #![no_std] | 5 | #![no_std] |
| 2 | #![no_main] | 6 | #![no_main] |
| 3 | #![feature(type_alias_impl_trait)] | 7 | #![feature(type_alias_impl_trait)] |
diff --git a/examples/rp/src/bin/rtc.rs b/examples/rp/src/bin/rtc.rs new file mode 100644 index 000000000..15aa8243f --- /dev/null +++ b/examples/rp/src/bin/rtc.rs | |||
| @@ -0,0 +1,46 @@ | |||
| 1 | //! This example shows how to use RTC (Real Time Clock) in the RP2040 chip. | ||
| 2 | |||
| 3 | #![no_std] | ||
| 4 | #![no_main] | ||
| 5 | #![feature(type_alias_impl_trait)] | ||
| 6 | |||
| 7 | use defmt::*; | ||
| 8 | use embassy_executor::Spawner; | ||
| 9 | use embassy_rp::rtc::{DateTime, DayOfWeek, Rtc}; | ||
| 10 | use embassy_time::{Duration, Timer}; | ||
| 11 | use {defmt_rtt as _, panic_probe as _}; | ||
| 12 | |||
| 13 | #[embassy_executor::main] | ||
| 14 | async fn main(_spawner: Spawner) { | ||
| 15 | let p = embassy_rp::init(Default::default()); | ||
| 16 | info!("Wait for 20s"); | ||
| 17 | |||
| 18 | let mut rtc = Rtc::new(p.RTC); | ||
| 19 | |||
| 20 | if !rtc.is_running() { | ||
| 21 | info!("Start RTC"); | ||
| 22 | let now = DateTime { | ||
| 23 | year: 2000, | ||
| 24 | month: 1, | ||
| 25 | day: 1, | ||
| 26 | day_of_week: DayOfWeek::Saturday, | ||
| 27 | hour: 0, | ||
| 28 | minute: 0, | ||
| 29 | second: 0, | ||
| 30 | }; | ||
| 31 | rtc.set_datetime(now).unwrap(); | ||
| 32 | } | ||
| 33 | |||
| 34 | Timer::after(Duration::from_millis(20000)).await; | ||
| 35 | |||
| 36 | if let Ok(dt) = rtc.now() { | ||
| 37 | info!( | ||
| 38 | "Now: {}-{:02}-{:02} {}:{:02}:{:02}", | ||
| 39 | dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second, | ||
| 40 | ); | ||
| 41 | } | ||
| 42 | |||
| 43 | info!("Reboot."); | ||
| 44 | Timer::after(Duration::from_millis(200)).await; | ||
| 45 | cortex_m::peripheral::SCB::sys_reset(); | ||
| 46 | } | ||
diff --git a/examples/rp/src/bin/spi.rs b/examples/rp/src/bin/spi.rs index a830a17a2..602348f7a 100644 --- a/examples/rp/src/bin/spi.rs +++ b/examples/rp/src/bin/spi.rs | |||
| @@ -1,3 +1,7 @@ | |||
| 1 | //! This example shows how to use SPI (Serial Peripheral Interface) in the RP2040 chip. | ||
| 2 | //! | ||
| 3 | //! Example for resistive touch sensor in Waveshare Pico-ResTouch | ||
| 4 | |||
| 1 | #![no_std] | 5 | #![no_std] |
| 2 | #![no_main] | 6 | #![no_main] |
| 3 | #![feature(type_alias_impl_trait)] | 7 | #![feature(type_alias_impl_trait)] |
diff --git a/examples/rp/src/bin/spi_async.rs b/examples/rp/src/bin/spi_async.rs index 671a9caaf..328074e8b 100644 --- a/examples/rp/src/bin/spi_async.rs +++ b/examples/rp/src/bin/spi_async.rs | |||
| @@ -1,3 +1,6 @@ | |||
| 1 | //! This example shows how to use SPI (Serial Peripheral Interface) in the RP2040 chip. | ||
| 2 | //! No specific hardware is specified in this example. If you connect pin 11 and 12 you should get the same data back. | ||
| 3 | |||
| 1 | #![no_std] | 4 | #![no_std] |
| 2 | #![no_main] | 5 | #![no_main] |
| 3 | #![feature(type_alias_impl_trait)] | 6 | #![feature(type_alias_impl_trait)] |
diff --git a/examples/rp/src/bin/spi_display.rs b/examples/rp/src/bin/spi_display.rs index 85a19ce07..26c258e1c 100644 --- a/examples/rp/src/bin/spi_display.rs +++ b/examples/rp/src/bin/spi_display.rs | |||
| @@ -1,3 +1,8 @@ | |||
| 1 | //! This example shows how to use SPI (Serial Peripheral Interface) in the RP2040 chip. | ||
| 2 | //! | ||
| 3 | //! Example written for a display using the ST7789 chip. Possibly the Waveshare Pico-ResTouch | ||
| 4 | //! (https://www.waveshare.com/wiki/Pico-ResTouch-LCD-2.8) | ||
| 5 | |||
| 1 | #![no_std] | 6 | #![no_std] |
| 2 | #![no_main] | 7 | #![no_main] |
| 3 | #![feature(type_alias_impl_trait)] | 8 | #![feature(type_alias_impl_trait)] |
| @@ -175,7 +180,7 @@ mod touch { | |||
| 175 | mod my_display_interface { | 180 | mod my_display_interface { |
| 176 | use display_interface::{DataFormat, DisplayError, WriteOnlyDataCommand}; | 181 | use display_interface::{DataFormat, DisplayError, WriteOnlyDataCommand}; |
| 177 | use embedded_hal_1::digital::OutputPin; | 182 | use embedded_hal_1::digital::OutputPin; |
| 178 | use embedded_hal_1::spi::SpiDeviceWrite; | 183 | use embedded_hal_1::spi::SpiDevice; |
| 179 | 184 | ||
| 180 | /// SPI display interface. | 185 | /// SPI display interface. |
| 181 | /// | 186 | /// |
| @@ -187,7 +192,7 @@ mod my_display_interface { | |||
| 187 | 192 | ||
| 188 | impl<SPI, DC> SPIDeviceInterface<SPI, DC> | 193 | impl<SPI, DC> SPIDeviceInterface<SPI, DC> |
| 189 | where | 194 | where |
| 190 | SPI: SpiDeviceWrite, | 195 | SPI: SpiDevice, |
| 191 | DC: OutputPin, | 196 | DC: OutputPin, |
| 192 | { | 197 | { |
| 193 | /// Create new SPI interface for communciation with a display driver | 198 | /// Create new SPI interface for communciation with a display driver |
| @@ -198,7 +203,7 @@ mod my_display_interface { | |||
| 198 | 203 | ||
| 199 | impl<SPI, DC> WriteOnlyDataCommand for SPIDeviceInterface<SPI, DC> | 204 | impl<SPI, DC> WriteOnlyDataCommand for SPIDeviceInterface<SPI, DC> |
| 200 | where | 205 | where |
| 201 | SPI: SpiDeviceWrite, | 206 | SPI: SpiDevice, |
| 202 | DC: OutputPin, | 207 | DC: OutputPin, |
| 203 | { | 208 | { |
| 204 | fn send_commands(&mut self, cmds: DataFormat<'_>) -> Result<(), DisplayError> { | 209 | fn send_commands(&mut self, cmds: DataFormat<'_>) -> Result<(), DisplayError> { |
| @@ -218,7 +223,7 @@ mod my_display_interface { | |||
| 218 | } | 223 | } |
| 219 | } | 224 | } |
| 220 | 225 | ||
| 221 | fn send_u8<T: SpiDeviceWrite>(spi: &mut T, words: DataFormat<'_>) -> Result<(), T::Error> { | 226 | fn send_u8<T: SpiDevice>(spi: &mut T, words: DataFormat<'_>) -> Result<(), T::Error> { |
| 222 | match words { | 227 | match words { |
| 223 | DataFormat::U8(slice) => spi.write(slice), | 228 | DataFormat::U8(slice) => spi.write(slice), |
| 224 | DataFormat::U16(slice) => { | 229 | DataFormat::U16(slice) => { |
diff --git a/examples/rp/src/bin/uart.rs b/examples/rp/src/bin/uart.rs index 05177a6b4..451c3c396 100644 --- a/examples/rp/src/bin/uart.rs +++ b/examples/rp/src/bin/uart.rs | |||
| @@ -1,3 +1,9 @@ | |||
| 1 | //! This example shows how to use UART (Universal asynchronous receiver-transmitter) in the RP2040 chip. | ||
| 2 | //! | ||
| 3 | //! No specific hardware is specified in this example. Only output on pin 0 is tested. | ||
| 4 | //! The Raspberry Pi Debug Probe (https://www.raspberrypi.com/products/debug-probe/) could be used | ||
| 5 | //! with its UART port. | ||
| 6 | |||
| 1 | #![no_std] | 7 | #![no_std] |
| 2 | #![no_main] | 8 | #![no_main] |
| 3 | #![feature(type_alias_impl_trait)] | 9 | #![feature(type_alias_impl_trait)] |
diff --git a/examples/rp/src/bin/uart_buffered_split.rs b/examples/rp/src/bin/uart_buffered_split.rs index 9df99bd58..735201718 100644 --- a/examples/rp/src/bin/uart_buffered_split.rs +++ b/examples/rp/src/bin/uart_buffered_split.rs | |||
| @@ -1,3 +1,9 @@ | |||
| 1 | //! This example shows how to use UART (Universal asynchronous receiver-transmitter) in the RP2040 chip. | ||
| 2 | //! | ||
| 3 | //! No specific hardware is specified in this example. If you connect pin 0 and 1 you should get the same data back. | ||
| 4 | //! The Raspberry Pi Debug Probe (https://www.raspberrypi.com/products/debug-probe/) could be used | ||
| 5 | //! with its UART port. | ||
| 6 | |||
| 1 | #![no_std] | 7 | #![no_std] |
| 2 | #![no_main] | 8 | #![no_main] |
| 3 | #![feature(type_alias_impl_trait)] | 9 | #![feature(type_alias_impl_trait)] |
diff --git a/examples/rp/src/bin/uart_unidir.rs b/examples/rp/src/bin/uart_unidir.rs index c0943a1b8..c1515a911 100644 --- a/examples/rp/src/bin/uart_unidir.rs +++ b/examples/rp/src/bin/uart_unidir.rs | |||
| @@ -1,5 +1,9 @@ | |||
| 1 | //! test TX-only and RX-only UARTs. You need to connect GPIO0 to GPIO5 for | 1 | //! This example shows how to use UART (Universal asynchronous receiver-transmitter) in the RP2040 chip. |
| 2 | //! | ||
| 3 | //! Test TX-only and RX-only on two different UARTs. You need to connect GPIO0 to GPIO5 for | ||
| 2 | //! this to work | 4 | //! this to work |
| 5 | //! The Raspberry Pi Debug Probe (https://www.raspberrypi.com/products/debug-probe/) could be used | ||
| 6 | //! with its UART port. | ||
| 3 | 7 | ||
| 4 | #![no_std] | 8 | #![no_std] |
| 5 | #![no_main] | 9 | #![no_main] |
diff --git a/examples/rp/src/bin/usb_ethernet.rs b/examples/rp/src/bin/usb_ethernet.rs index 91d1ec8e7..0a08f667e 100644 --- a/examples/rp/src/bin/usb_ethernet.rs +++ b/examples/rp/src/bin/usb_ethernet.rs | |||
| @@ -1,3 +1,7 @@ | |||
| 1 | //! This example shows how to use USB (Universal Serial Bus) in the RP2040 chip. | ||
| 2 | //! | ||
| 3 | //! This is a CDC-NCM class implementation, aka Ethernet over USB. | ||
| 4 | |||
| 1 | #![no_std] | 5 | #![no_std] |
| 2 | #![no_main] | 6 | #![no_main] |
| 3 | #![feature(type_alias_impl_trait)] | 7 | #![feature(type_alias_impl_trait)] |
diff --git a/examples/rp/src/bin/usb_hid_keyboard.rs b/examples/rp/src/bin/usb_hid_keyboard.rs new file mode 100644 index 000000000..99af1f02f --- /dev/null +++ b/examples/rp/src/bin/usb_hid_keyboard.rs | |||
| @@ -0,0 +1,188 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | #![feature(type_alias_impl_trait)] | ||
| 4 | |||
| 5 | use core::sync::atomic::{AtomicBool, Ordering}; | ||
| 6 | |||
| 7 | use defmt::*; | ||
| 8 | use embassy_executor::Spawner; | ||
| 9 | use embassy_futures::join::join; | ||
| 10 | use embassy_rp::bind_interrupts; | ||
| 11 | use embassy_rp::gpio::{Input, Pull}; | ||
| 12 | use embassy_rp::peripherals::USB; | ||
| 13 | use embassy_rp::usb::{Driver, InterruptHandler}; | ||
| 14 | use embassy_usb::class::hid::{HidReaderWriter, ReportId, RequestHandler, State}; | ||
| 15 | use embassy_usb::control::OutResponse; | ||
| 16 | use embassy_usb::{Builder, Config, Handler}; | ||
| 17 | use usbd_hid::descriptor::{KeyboardReport, SerializedDescriptor}; | ||
| 18 | use {defmt_rtt as _, panic_probe as _}; | ||
| 19 | |||
| 20 | bind_interrupts!(struct Irqs { | ||
| 21 | USBCTRL_IRQ => InterruptHandler<USB>; | ||
| 22 | }); | ||
| 23 | |||
| 24 | #[embassy_executor::main] | ||
| 25 | async fn main(_spawner: Spawner) { | ||
| 26 | let p = embassy_rp::init(Default::default()); | ||
| 27 | // Create the driver, from the HAL. | ||
| 28 | let driver = Driver::new(p.USB, Irqs); | ||
| 29 | |||
| 30 | // Create embassy-usb Config | ||
| 31 | let mut config = Config::new(0xc0de, 0xcafe); | ||
| 32 | config.manufacturer = Some("Embassy"); | ||
| 33 | config.product = Some("HID keyboard example"); | ||
| 34 | config.serial_number = Some("12345678"); | ||
| 35 | config.max_power = 100; | ||
| 36 | config.max_packet_size_0 = 64; | ||
| 37 | |||
| 38 | // Create embassy-usb DeviceBuilder using the driver and config. | ||
| 39 | // It needs some buffers for building the descriptors. | ||
| 40 | let mut device_descriptor = [0; 256]; | ||
| 41 | let mut config_descriptor = [0; 256]; | ||
| 42 | let mut bos_descriptor = [0; 256]; | ||
| 43 | // You can also add a Microsoft OS descriptor. | ||
| 44 | // let mut msos_descriptor = [0; 256]; | ||
| 45 | let mut control_buf = [0; 64]; | ||
| 46 | let request_handler = MyRequestHandler {}; | ||
| 47 | let mut device_handler = MyDeviceHandler::new(); | ||
| 48 | |||
| 49 | let mut state = State::new(); | ||
| 50 | |||
| 51 | let mut builder = Builder::new( | ||
| 52 | driver, | ||
| 53 | config, | ||
| 54 | &mut device_descriptor, | ||
| 55 | &mut config_descriptor, | ||
| 56 | &mut bos_descriptor, | ||
| 57 | // &mut msos_descriptor, | ||
| 58 | &mut control_buf, | ||
| 59 | ); | ||
| 60 | |||
| 61 | builder.handler(&mut device_handler); | ||
| 62 | |||
| 63 | // Create classes on the builder. | ||
| 64 | let config = embassy_usb::class::hid::Config { | ||
| 65 | report_descriptor: KeyboardReport::desc(), | ||
| 66 | request_handler: Some(&request_handler), | ||
| 67 | poll_ms: 60, | ||
| 68 | max_packet_size: 64, | ||
| 69 | }; | ||
| 70 | let hid = HidReaderWriter::<_, 1, 8>::new(&mut builder, &mut state, config); | ||
| 71 | |||
| 72 | // Build the builder. | ||
| 73 | let mut usb = builder.build(); | ||
| 74 | |||
| 75 | // Run the USB device. | ||
| 76 | let usb_fut = usb.run(); | ||
| 77 | |||
| 78 | // Set up the signal pin that will be used to trigger the keyboard. | ||
| 79 | let mut signal_pin = Input::new(p.PIN_16, Pull::None); | ||
| 80 | |||
| 81 | let (reader, mut writer) = hid.split(); | ||
| 82 | |||
| 83 | // Do stuff with the class! | ||
| 84 | let in_fut = async { | ||
| 85 | loop { | ||
| 86 | info!("Waiting for HIGH on pin 16"); | ||
| 87 | signal_pin.wait_for_high().await; | ||
| 88 | info!("HIGH DETECTED"); | ||
| 89 | // Create a report with the A key pressed. (no shift modifier) | ||
| 90 | let report = KeyboardReport { | ||
| 91 | keycodes: [4, 0, 0, 0, 0, 0], | ||
| 92 | leds: 0, | ||
| 93 | modifier: 0, | ||
| 94 | reserved: 0, | ||
| 95 | }; | ||
| 96 | // Send the report. | ||
| 97 | match writer.write_serialize(&report).await { | ||
| 98 | Ok(()) => {} | ||
| 99 | Err(e) => warn!("Failed to send report: {:?}", e), | ||
| 100 | }; | ||
| 101 | signal_pin.wait_for_low().await; | ||
| 102 | info!("LOW DETECTED"); | ||
| 103 | let report = KeyboardReport { | ||
| 104 | keycodes: [0, 0, 0, 0, 0, 0], | ||
| 105 | leds: 0, | ||
| 106 | modifier: 0, | ||
| 107 | reserved: 0, | ||
| 108 | }; | ||
| 109 | match writer.write_serialize(&report).await { | ||
| 110 | Ok(()) => {} | ||
| 111 | Err(e) => warn!("Failed to send report: {:?}", e), | ||
| 112 | }; | ||
| 113 | } | ||
| 114 | }; | ||
| 115 | |||
| 116 | let out_fut = async { | ||
| 117 | reader.run(false, &request_handler).await; | ||
| 118 | }; | ||
| 119 | |||
| 120 | // Run everything concurrently. | ||
| 121 | // If we had made everything `'static` above instead, we could do this using separate tasks instead. | ||
| 122 | join(usb_fut, join(in_fut, out_fut)).await; | ||
| 123 | } | ||
| 124 | |||
| 125 | struct MyRequestHandler {} | ||
| 126 | |||
| 127 | impl RequestHandler for MyRequestHandler { | ||
| 128 | fn get_report(&self, id: ReportId, _buf: &mut [u8]) -> Option<usize> { | ||
| 129 | info!("Get report for {:?}", id); | ||
| 130 | None | ||
| 131 | } | ||
| 132 | |||
| 133 | fn set_report(&self, id: ReportId, data: &[u8]) -> OutResponse { | ||
| 134 | info!("Set report for {:?}: {=[u8]}", id, data); | ||
| 135 | OutResponse::Accepted | ||
| 136 | } | ||
| 137 | |||
| 138 | fn set_idle_ms(&self, id: Option<ReportId>, dur: u32) { | ||
| 139 | info!("Set idle rate for {:?} to {:?}", id, dur); | ||
| 140 | } | ||
| 141 | |||
| 142 | fn get_idle_ms(&self, id: Option<ReportId>) -> Option<u32> { | ||
| 143 | info!("Get idle rate for {:?}", id); | ||
| 144 | None | ||
| 145 | } | ||
| 146 | } | ||
| 147 | |||
| 148 | struct MyDeviceHandler { | ||
| 149 | configured: AtomicBool, | ||
| 150 | } | ||
| 151 | |||
| 152 | impl MyDeviceHandler { | ||
| 153 | fn new() -> Self { | ||
| 154 | MyDeviceHandler { | ||
| 155 | configured: AtomicBool::new(false), | ||
| 156 | } | ||
| 157 | } | ||
| 158 | } | ||
| 159 | |||
| 160 | impl Handler for MyDeviceHandler { | ||
| 161 | fn enabled(&mut self, enabled: bool) { | ||
| 162 | self.configured.store(false, Ordering::Relaxed); | ||
| 163 | if enabled { | ||
| 164 | info!("Device enabled"); | ||
| 165 | } else { | ||
| 166 | info!("Device disabled"); | ||
| 167 | } | ||
| 168 | } | ||
| 169 | |||
| 170 | fn reset(&mut self) { | ||
| 171 | self.configured.store(false, Ordering::Relaxed); | ||
| 172 | info!("Bus reset, the Vbus current limit is 100mA"); | ||
| 173 | } | ||
| 174 | |||
| 175 | fn addressed(&mut self, addr: u8) { | ||
| 176 | self.configured.store(false, Ordering::Relaxed); | ||
| 177 | info!("USB address set to: {}", addr); | ||
| 178 | } | ||
| 179 | |||
| 180 | fn configured(&mut self, configured: bool) { | ||
| 181 | self.configured.store(configured, Ordering::Relaxed); | ||
| 182 | if configured { | ||
| 183 | info!("Device configured, it may now draw up to the configured current limit from Vbus.") | ||
| 184 | } else { | ||
| 185 | info!("Device is no longer configured, the Vbus current limit is 100mA."); | ||
| 186 | } | ||
| 187 | } | ||
| 188 | } | ||
diff --git a/examples/rp/src/bin/usb_logger.rs b/examples/rp/src/bin/usb_logger.rs index 7c90d0ca3..9c5e6897d 100644 --- a/examples/rp/src/bin/usb_logger.rs +++ b/examples/rp/src/bin/usb_logger.rs | |||
| @@ -1,3 +1,7 @@ | |||
| 1 | //! This example shows how to use USB (Universal Serial Bus) in the RP2040 chip. | ||
| 2 | //! | ||
| 3 | //! This creates the possibility to send log::info/warn/error/debug! to USB serial port. | ||
| 4 | |||
| 1 | #![no_std] | 5 | #![no_std] |
| 2 | #![no_main] | 6 | #![no_main] |
| 3 | #![feature(type_alias_impl_trait)] | 7 | #![feature(type_alias_impl_trait)] |
diff --git a/examples/rp/src/bin/usb_serial.rs b/examples/rp/src/bin/usb_serial.rs index ca728536c..164e2052d 100644 --- a/examples/rp/src/bin/usb_serial.rs +++ b/examples/rp/src/bin/usb_serial.rs | |||
| @@ -1,3 +1,7 @@ | |||
| 1 | //! This example shows how to use USB (Universal Serial Bus) in the RP2040 chip. | ||
| 2 | //! | ||
| 3 | //! This creates a USB serial port that echos. | ||
| 4 | |||
| 1 | #![no_std] | 5 | #![no_std] |
| 2 | #![no_main] | 6 | #![no_main] |
| 3 | #![feature(type_alias_impl_trait)] | 7 | #![feature(type_alias_impl_trait)] |
diff --git a/examples/rp/src/bin/watchdog.rs b/examples/rp/src/bin/watchdog.rs index ece5cfe38..fe5eaf926 100644 --- a/examples/rp/src/bin/watchdog.rs +++ b/examples/rp/src/bin/watchdog.rs | |||
| @@ -1,3 +1,7 @@ | |||
| 1 | //! This example shows how to use Watchdog in the RP2040 chip. | ||
| 2 | //! | ||
| 3 | //! It does not work with the RP Pico W board. See wifi_blinky.rs or connect external LED and resistor. | ||
| 4 | |||
| 1 | #![no_std] | 5 | #![no_std] |
| 2 | #![no_main] | 6 | #![no_main] |
| 3 | #![feature(type_alias_impl_trait)] | 7 | #![feature(type_alias_impl_trait)] |
diff --git a/examples/rp/src/bin/wifi_ap_tcp_server.rs b/examples/rp/src/bin/wifi_ap_tcp_server.rs index 310e84d92..e3e393445 100644 --- a/examples/rp/src/bin/wifi_ap_tcp_server.rs +++ b/examples/rp/src/bin/wifi_ap_tcp_server.rs | |||
| @@ -1,3 +1,6 @@ | |||
| 1 | //! This example uses the RP Pico W board Wifi chip (cyw43). | ||
| 2 | //! Creates an Access point Wifi network and creates a TCP endpoint on port 1234. | ||
| 3 | |||
| 1 | #![no_std] | 4 | #![no_std] |
| 2 | #![no_main] | 5 | #![no_main] |
| 3 | #![feature(type_alias_impl_trait)] | 6 | #![feature(type_alias_impl_trait)] |
| @@ -11,14 +14,19 @@ use defmt::*; | |||
| 11 | use embassy_executor::Spawner; | 14 | use embassy_executor::Spawner; |
| 12 | use embassy_net::tcp::TcpSocket; | 15 | use embassy_net::tcp::TcpSocket; |
| 13 | use embassy_net::{Config, Stack, StackResources}; | 16 | use embassy_net::{Config, Stack, StackResources}; |
| 17 | use embassy_rp::bind_interrupts; | ||
| 14 | use embassy_rp::gpio::{Level, Output}; | 18 | use embassy_rp::gpio::{Level, Output}; |
| 15 | use embassy_rp::peripherals::{DMA_CH0, PIN_23, PIN_25, PIO0}; | 19 | use embassy_rp::peripherals::{DMA_CH0, PIN_23, PIN_25, PIO0}; |
| 16 | use embassy_rp::pio::Pio; | 20 | use embassy_rp::pio::{InterruptHandler, Pio}; |
| 17 | use embassy_time::Duration; | 21 | use embassy_time::Duration; |
| 18 | use embedded_io::asynch::Write; | 22 | use embedded_io::asynch::Write; |
| 19 | use static_cell::make_static; | 23 | use static_cell::make_static; |
| 20 | use {defmt_rtt as _, panic_probe as _}; | 24 | use {defmt_rtt as _, panic_probe as _}; |
| 21 | 25 | ||
| 26 | bind_interrupts!(struct Irqs { | ||
| 27 | PIO0_IRQ_0 => InterruptHandler<PIO0>; | ||
| 28 | }); | ||
| 29 | |||
| 22 | #[embassy_executor::task] | 30 | #[embassy_executor::task] |
| 23 | async fn wifi_task( | 31 | async fn wifi_task( |
| 24 | runner: cyw43::Runner<'static, Output<'static, PIN_23>, PioSpi<'static, PIN_25, PIO0, 0, DMA_CH0>>, | 32 | runner: cyw43::Runner<'static, Output<'static, PIN_23>, PioSpi<'static, PIN_25, PIO0, 0, DMA_CH0>>, |
| @@ -49,7 +57,7 @@ async fn main(spawner: Spawner) { | |||
| 49 | 57 | ||
| 50 | let pwr = Output::new(p.PIN_23, Level::Low); | 58 | let pwr = Output::new(p.PIN_23, Level::Low); |
| 51 | let cs = Output::new(p.PIN_25, Level::High); | 59 | let cs = Output::new(p.PIN_25, Level::High); |
| 52 | let mut pio = Pio::new(p.PIO0); | 60 | let mut pio = Pio::new(p.PIO0, Irqs); |
| 53 | let spi = PioSpi::new(&mut pio.common, pio.sm0, pio.irq0, cs, p.PIN_24, p.PIN_29, p.DMA_CH0); | 61 | let spi = PioSpi::new(&mut pio.common, pio.sm0, pio.irq0, cs, p.PIN_24, p.PIN_29, p.DMA_CH0); |
| 54 | 62 | ||
| 55 | let state = make_static!(cyw43::State::new()); | 63 | let state = make_static!(cyw43::State::new()); |
diff --git a/examples/rp/src/bin/wifi_blinky.rs b/examples/rp/src/bin/wifi_blinky.rs index bbcb1b5ec..33d43788c 100644 --- a/examples/rp/src/bin/wifi_blinky.rs +++ b/examples/rp/src/bin/wifi_blinky.rs | |||
| @@ -1,3 +1,7 @@ | |||
| 1 | //! This example test the RP Pico W on board LED. | ||
| 2 | //! | ||
| 3 | //! It does not work with the RP Pico board. See blinky.rs. | ||
| 4 | |||
| 1 | #![no_std] | 5 | #![no_std] |
| 2 | #![no_main] | 6 | #![no_main] |
| 3 | #![feature(type_alias_impl_trait)] | 7 | #![feature(type_alias_impl_trait)] |
| @@ -5,13 +9,18 @@ | |||
| 5 | use cyw43_pio::PioSpi; | 9 | use cyw43_pio::PioSpi; |
| 6 | use defmt::*; | 10 | use defmt::*; |
| 7 | use embassy_executor::Spawner; | 11 | use embassy_executor::Spawner; |
| 12 | use embassy_rp::bind_interrupts; | ||
| 8 | use embassy_rp::gpio::{Level, Output}; | 13 | use embassy_rp::gpio::{Level, Output}; |
| 9 | use embassy_rp::peripherals::{DMA_CH0, PIN_23, PIN_25, PIO0}; | 14 | use embassy_rp::peripherals::{DMA_CH0, PIN_23, PIN_25, PIO0}; |
| 10 | use embassy_rp::pio::Pio; | 15 | use embassy_rp::pio::{InterruptHandler, Pio}; |
| 11 | use embassy_time::{Duration, Timer}; | 16 | use embassy_time::{Duration, Timer}; |
| 12 | use static_cell::make_static; | 17 | use static_cell::make_static; |
| 13 | use {defmt_rtt as _, panic_probe as _}; | 18 | use {defmt_rtt as _, panic_probe as _}; |
| 14 | 19 | ||
| 20 | bind_interrupts!(struct Irqs { | ||
| 21 | PIO0_IRQ_0 => InterruptHandler<PIO0>; | ||
| 22 | }); | ||
| 23 | |||
| 15 | #[embassy_executor::task] | 24 | #[embassy_executor::task] |
| 16 | async fn wifi_task( | 25 | async fn wifi_task( |
| 17 | runner: cyw43::Runner<'static, Output<'static, PIN_23>, PioSpi<'static, PIN_25, PIO0, 0, DMA_CH0>>, | 26 | runner: cyw43::Runner<'static, Output<'static, PIN_23>, PioSpi<'static, PIN_25, PIO0, 0, DMA_CH0>>, |
| @@ -34,7 +43,7 @@ async fn main(spawner: Spawner) { | |||
| 34 | 43 | ||
| 35 | let pwr = Output::new(p.PIN_23, Level::Low); | 44 | let pwr = Output::new(p.PIN_23, Level::Low); |
| 36 | let cs = Output::new(p.PIN_25, Level::High); | 45 | let cs = Output::new(p.PIN_25, Level::High); |
| 37 | let mut pio = Pio::new(p.PIO0); | 46 | let mut pio = Pio::new(p.PIO0, Irqs); |
| 38 | let spi = PioSpi::new(&mut pio.common, pio.sm0, pio.irq0, cs, p.PIN_24, p.PIN_29, p.DMA_CH0); | 47 | let spi = PioSpi::new(&mut pio.common, pio.sm0, pio.irq0, cs, p.PIN_24, p.PIN_29, p.DMA_CH0); |
| 39 | 48 | ||
| 40 | let state = make_static!(cyw43::State::new()); | 49 | let state = make_static!(cyw43::State::new()); |
diff --git a/examples/rp/src/bin/wifi_scan.rs b/examples/rp/src/bin/wifi_scan.rs index 391e12282..743fab617 100644 --- a/examples/rp/src/bin/wifi_scan.rs +++ b/examples/rp/src/bin/wifi_scan.rs | |||
| @@ -1,3 +1,6 @@ | |||
| 1 | //! This example uses the RP Pico W board Wifi chip (cyw43). | ||
| 2 | //! Scans Wifi for ssid names. | ||
| 3 | |||
| 1 | #![no_std] | 4 | #![no_std] |
| 2 | #![no_main] | 5 | #![no_main] |
| 3 | #![feature(type_alias_impl_trait)] | 6 | #![feature(type_alias_impl_trait)] |
| @@ -10,12 +13,17 @@ use cyw43_pio::PioSpi; | |||
| 10 | use defmt::*; | 13 | use defmt::*; |
| 11 | use embassy_executor::Spawner; | 14 | use embassy_executor::Spawner; |
| 12 | use embassy_net::Stack; | 15 | use embassy_net::Stack; |
| 16 | use embassy_rp::bind_interrupts; | ||
| 13 | use embassy_rp::gpio::{Level, Output}; | 17 | use embassy_rp::gpio::{Level, Output}; |
| 14 | use embassy_rp::peripherals::{DMA_CH0, PIN_23, PIN_25, PIO0}; | 18 | use embassy_rp::peripherals::{DMA_CH0, PIN_23, PIN_25, PIO0}; |
| 15 | use embassy_rp::pio::Pio; | 19 | use embassy_rp::pio::{InterruptHandler, Pio}; |
| 16 | use static_cell::make_static; | 20 | use static_cell::make_static; |
| 17 | use {defmt_rtt as _, panic_probe as _}; | 21 | use {defmt_rtt as _, panic_probe as _}; |
| 18 | 22 | ||
| 23 | bind_interrupts!(struct Irqs { | ||
| 24 | PIO0_IRQ_0 => InterruptHandler<PIO0>; | ||
| 25 | }); | ||
| 26 | |||
| 19 | #[embassy_executor::task] | 27 | #[embassy_executor::task] |
| 20 | async fn wifi_task( | 28 | async fn wifi_task( |
| 21 | runner: cyw43::Runner<'static, Output<'static, PIN_23>, PioSpi<'static, PIN_25, PIO0, 0, DMA_CH0>>, | 29 | runner: cyw43::Runner<'static, Output<'static, PIN_23>, PioSpi<'static, PIN_25, PIO0, 0, DMA_CH0>>, |
| @@ -46,7 +54,7 @@ async fn main(spawner: Spawner) { | |||
| 46 | 54 | ||
| 47 | let pwr = Output::new(p.PIN_23, Level::Low); | 55 | let pwr = Output::new(p.PIN_23, Level::Low); |
| 48 | let cs = Output::new(p.PIN_25, Level::High); | 56 | let cs = Output::new(p.PIN_25, Level::High); |
| 49 | let mut pio = Pio::new(p.PIO0); | 57 | let mut pio = Pio::new(p.PIO0, Irqs); |
| 50 | let spi = PioSpi::new(&mut pio.common, pio.sm0, pio.irq0, cs, p.PIN_24, p.PIN_29, p.DMA_CH0); | 58 | let spi = PioSpi::new(&mut pio.common, pio.sm0, pio.irq0, cs, p.PIN_24, p.PIN_29, p.DMA_CH0); |
| 51 | 59 | ||
| 52 | let state = make_static!(cyw43::State::new()); | 60 | let state = make_static!(cyw43::State::new()); |
diff --git a/examples/rp/src/bin/wifi_tcp_server.rs b/examples/rp/src/bin/wifi_tcp_server.rs index e9d1079a6..0223a3636 100644 --- a/examples/rp/src/bin/wifi_tcp_server.rs +++ b/examples/rp/src/bin/wifi_tcp_server.rs | |||
| @@ -1,3 +1,6 @@ | |||
| 1 | //! This example uses the RP Pico W board Wifi chip (cyw43). | ||
| 2 | //! Connects to specified Wifi network and creates a TCP endpoint on port 1234. | ||
| 3 | |||
| 1 | #![no_std] | 4 | #![no_std] |
| 2 | #![no_main] | 5 | #![no_main] |
| 3 | #![feature(type_alias_impl_trait)] | 6 | #![feature(type_alias_impl_trait)] |
| @@ -11,14 +14,22 @@ use defmt::*; | |||
| 11 | use embassy_executor::Spawner; | 14 | use embassy_executor::Spawner; |
| 12 | use embassy_net::tcp::TcpSocket; | 15 | use embassy_net::tcp::TcpSocket; |
| 13 | use embassy_net::{Config, Stack, StackResources}; | 16 | use embassy_net::{Config, Stack, StackResources}; |
| 17 | use embassy_rp::bind_interrupts; | ||
| 14 | use embassy_rp::gpio::{Level, Output}; | 18 | use embassy_rp::gpio::{Level, Output}; |
| 15 | use embassy_rp::peripherals::{DMA_CH0, PIN_23, PIN_25, PIO0}; | 19 | use embassy_rp::peripherals::{DMA_CH0, PIN_23, PIN_25, PIO0}; |
| 16 | use embassy_rp::pio::Pio; | 20 | use embassy_rp::pio::{InterruptHandler, Pio}; |
| 17 | use embassy_time::Duration; | 21 | use embassy_time::Duration; |
| 18 | use embedded_io::asynch::Write; | 22 | use embedded_io::asynch::Write; |
| 19 | use static_cell::make_static; | 23 | use static_cell::make_static; |
| 20 | use {defmt_rtt as _, panic_probe as _}; | 24 | use {defmt_rtt as _, panic_probe as _}; |
| 21 | 25 | ||
| 26 | bind_interrupts!(struct Irqs { | ||
| 27 | PIO0_IRQ_0 => InterruptHandler<PIO0>; | ||
| 28 | }); | ||
| 29 | |||
| 30 | const WIFI_NETWORK: &str = "EmbassyTest"; | ||
| 31 | const WIFI_PASSWORD: &str = "V8YxhKt5CdIAJFud"; | ||
| 32 | |||
| 22 | #[embassy_executor::task] | 33 | #[embassy_executor::task] |
| 23 | async fn wifi_task( | 34 | async fn wifi_task( |
| 24 | runner: cyw43::Runner<'static, Output<'static, PIN_23>, PioSpi<'static, PIN_25, PIO0, 0, DMA_CH0>>, | 35 | runner: cyw43::Runner<'static, Output<'static, PIN_23>, PioSpi<'static, PIN_25, PIO0, 0, DMA_CH0>>, |
| @@ -49,7 +60,7 @@ async fn main(spawner: Spawner) { | |||
| 49 | 60 | ||
| 50 | let pwr = Output::new(p.PIN_23, Level::Low); | 61 | let pwr = Output::new(p.PIN_23, Level::Low); |
| 51 | let cs = Output::new(p.PIN_25, Level::High); | 62 | let cs = Output::new(p.PIN_25, Level::High); |
| 52 | let mut pio = Pio::new(p.PIO0); | 63 | let mut pio = Pio::new(p.PIO0, Irqs); |
| 53 | let spi = PioSpi::new(&mut pio.common, pio.sm0, pio.irq0, cs, p.PIN_24, p.PIN_29, p.DMA_CH0); | 64 | let spi = PioSpi::new(&mut pio.common, pio.sm0, pio.irq0, cs, p.PIN_24, p.PIN_29, p.DMA_CH0); |
| 54 | 65 | ||
| 55 | let state = make_static!(cyw43::State::new()); | 66 | let state = make_static!(cyw43::State::new()); |
| @@ -82,8 +93,8 @@ async fn main(spawner: Spawner) { | |||
| 82 | unwrap!(spawner.spawn(net_task(stack))); | 93 | unwrap!(spawner.spawn(net_task(stack))); |
| 83 | 94 | ||
| 84 | loop { | 95 | loop { |
| 85 | //control.join_open(env!("WIFI_NETWORK")).await; | 96 | //control.join_open(WIFI_NETWORK).await; |
| 86 | match control.join_wpa2(env!("WIFI_NETWORK"), env!("WIFI_PASSWORD")).await { | 97 | match control.join_wpa2(WIFI_NETWORK, WIFI_PASSWORD).await { |
| 87 | Ok(_) => break, | 98 | Ok(_) => break, |
| 88 | Err(err) => { | 99 | Err(err) => { |
| 89 | info!("join failed with status={}", err.status); | 100 | info!("join failed with status={}", err.status); |
diff --git a/examples/std/Cargo.toml b/examples/std/Cargo.toml index 878ad8c5a..92933ab50 100644 --- a/examples/std/Cargo.toml +++ b/examples/std/Cargo.toml | |||
| @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" | |||
| 7 | [dependencies] | 7 | [dependencies] |
| 8 | embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["log"] } | 8 | embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["log"] } |
| 9 | embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["arch-std", "executor-thread", "log", "nightly", "integrated-timers"] } | 9 | embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["arch-std", "executor-thread", "log", "nightly", "integrated-timers"] } |
| 10 | embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["log", "std", "nightly"] } | 10 | embassy-time = { version = "0.1.2", path = "../../embassy-time", features = ["log", "std", "nightly"] } |
| 11 | embassy-net = { version = "0.1.0", path = "../../embassy-net", features=[ "std", "nightly", "log", "medium-ethernet", "tcp", "udp", "dns", "dhcpv4", "unstable-traits", "proto-ipv6"] } | 11 | embassy-net = { version = "0.1.0", path = "../../embassy-net", features=[ "std", "nightly", "log", "medium-ethernet", "tcp", "udp", "dns", "dhcpv4", "unstable-traits", "proto-ipv6"] } |
| 12 | embassy-net-driver = { version = "0.1.0", path = "../../embassy-net-driver" } | 12 | embassy-net-driver = { version = "0.1.0", path = "../../embassy-net-driver" } |
| 13 | embedded-io = { version = "0.4.0", features = ["async", "std", "futures"] } | 13 | embedded-io = { version = "0.4.0", features = ["async", "std", "futures"] } |
diff --git a/examples/stm32c0/Cargo.toml b/examples/stm32c0/Cargo.toml index 43f432520..26837abef 100644 --- a/examples/stm32c0/Cargo.toml +++ b/examples/stm32c0/Cargo.toml | |||
| @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" | |||
| 7 | [dependencies] | 7 | [dependencies] |
| 8 | embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] } | 8 | embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] } |
| 9 | embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } | 9 | embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } |
| 10 | embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } | 10 | embassy-time = { version = "0.1.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } |
| 11 | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "time-driver-any", "stm32c031c6", "memory-x", "unstable-pac", "exti"] } | 11 | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "time-driver-any", "stm32c031c6", "memory-x", "unstable-pac", "exti"] } |
| 12 | 12 | ||
| 13 | defmt = "0.3" | 13 | defmt = "0.3" |
diff --git a/examples/stm32f0/Cargo.toml b/examples/stm32f0/Cargo.toml index 8d2248ed0..b7b5eaa99 100644 --- a/examples/stm32f0/Cargo.toml +++ b/examples/stm32f0/Cargo.toml | |||
| @@ -14,6 +14,6 @@ defmt-rtt = "0.4" | |||
| 14 | panic-probe = "0.3" | 14 | panic-probe = "0.3" |
| 15 | embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] } | 15 | embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] } |
| 16 | embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] } | 16 | embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] } |
| 17 | embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } | 17 | embassy-time = { version = "0.1.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } |
| 18 | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "memory-x", "stm32f091rc", "time-driver-any", "exti", "unstable-pac"] } | 18 | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "memory-x", "stm32f091rc", "time-driver-any", "exti", "unstable-pac"] } |
| 19 | static_cell = { version = "1.1", features = ["nightly"]} | 19 | static_cell = { version = "1.1", features = ["nightly"]} |
diff --git a/examples/stm32f1/Cargo.toml b/examples/stm32f1/Cargo.toml index d34fd439a..29cad5b67 100644 --- a/examples/stm32f1/Cargo.toml +++ b/examples/stm32f1/Cargo.toml | |||
| @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" | |||
| 7 | [dependencies] | 7 | [dependencies] |
| 8 | embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] } | 8 | embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] } |
| 9 | embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } | 9 | embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } |
| 10 | embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } | 10 | embassy-time = { version = "0.1.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } |
| 11 | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32f103c8", "unstable-pac", "memory-x", "time-driver-any", "unstable-traits" ] } | 11 | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32f103c8", "unstable-pac", "memory-x", "time-driver-any", "unstable-traits" ] } |
| 12 | embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] } | 12 | embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] } |
| 13 | embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } | 13 | embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } |
diff --git a/examples/stm32f2/Cargo.toml b/examples/stm32f2/Cargo.toml index 5e3e0d0f7..652210c7f 100644 --- a/examples/stm32f2/Cargo.toml +++ b/examples/stm32f2/Cargo.toml | |||
| @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" | |||
| 7 | [dependencies] | 7 | [dependencies] |
| 8 | embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] } | 8 | embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] } |
| 9 | embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } | 9 | embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } |
| 10 | embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } | 10 | embassy-time = { version = "0.1.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } |
| 11 | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32f207zg", "unstable-pac", "memory-x", "time-driver-any", "exti"] } | 11 | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32f207zg", "unstable-pac", "memory-x", "time-driver-any", "exti"] } |
| 12 | 12 | ||
| 13 | defmt = "0.3" | 13 | defmt = "0.3" |
diff --git a/examples/stm32f3/Cargo.toml b/examples/stm32f3/Cargo.toml index 29ab2009c..489d0ff4c 100644 --- a/examples/stm32f3/Cargo.toml +++ b/examples/stm32f3/Cargo.toml | |||
| @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" | |||
| 7 | [dependencies] | 7 | [dependencies] |
| 8 | embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] } | 8 | embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] } |
| 9 | embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] } | 9 | embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] } |
| 10 | embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } | 10 | embassy-time = { version = "0.1.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } |
| 11 | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32f303ze", "unstable-pac", "memory-x", "time-driver-any", "exti"] } | 11 | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32f303ze", "unstable-pac", "memory-x", "time-driver-any", "exti"] } |
| 12 | embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] } | 12 | embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] } |
| 13 | embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } | 13 | embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } |
diff --git a/examples/stm32f4/Cargo.toml b/examples/stm32f4/Cargo.toml index 7ecb64fce..c1c821364 100644 --- a/examples/stm32f4/Cargo.toml +++ b/examples/stm32f4/Cargo.toml | |||
| @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" | |||
| 7 | [dependencies] | 7 | [dependencies] |
| 8 | embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] } | 8 | embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] } |
| 9 | embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers", "arch-cortex-m", "executor-thread", "executor-interrupt"] } | 9 | embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers", "arch-cortex-m", "executor-thread", "executor-interrupt"] } |
| 10 | embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "unstable-traits", "tick-hz-32_768"] } | 10 | embassy-time = { version = "0.1.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "unstable-traits", "tick-hz-32_768"] } |
| 11 | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "unstable-traits", "defmt", "stm32f429zi", "unstable-pac", "memory-x", "time-driver-any", "exti", "embedded-sdmmc", "chrono"] } | 11 | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "unstable-traits", "defmt", "stm32f429zi", "unstable-pac", "memory-x", "time-driver-any", "exti", "embedded-sdmmc", "chrono"] } |
| 12 | embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] } | 12 | embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] } |
| 13 | embassy-net = { version = "0.1.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", "nightly"] } | 13 | embassy-net = { version = "0.1.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", "nightly"] } |
diff --git a/examples/stm32f4/src/bin/can.rs b/examples/stm32f4/src/bin/can.rs index da8955053..08bed88db 100644 --- a/examples/stm32f4/src/bin/can.rs +++ b/examples/stm32f4/src/bin/can.rs | |||
| @@ -2,8 +2,8 @@ | |||
| 2 | #![no_main] | 2 | #![no_main] |
| 3 | #![feature(type_alias_impl_trait)] | 3 | #![feature(type_alias_impl_trait)] |
| 4 | 4 | ||
| 5 | use cortex_m_rt::entry; | ||
| 6 | use defmt::*; | 5 | use defmt::*; |
| 6 | use embassy_executor::Spawner; | ||
| 7 | use embassy_stm32::bind_interrupts; | 7 | use embassy_stm32::bind_interrupts; |
| 8 | use embassy_stm32::can::bxcan::filter::Mask32; | 8 | use embassy_stm32::can::bxcan::filter::Mask32; |
| 9 | use embassy_stm32::can::bxcan::{Fifo, Frame, StandardId}; | 9 | use embassy_stm32::can::bxcan::{Fifo, Frame, StandardId}; |
| @@ -19,8 +19,8 @@ bind_interrupts!(struct Irqs { | |||
| 19 | CAN1_TX => TxInterruptHandler<CAN1>; | 19 | CAN1_TX => TxInterruptHandler<CAN1>; |
| 20 | }); | 20 | }); |
| 21 | 21 | ||
| 22 | #[entry] | 22 | #[embassy_executor::main] |
| 23 | fn main() -> ! { | 23 | async fn main(_spawner: Spawner) { |
| 24 | info!("Hello World!"); | 24 | info!("Hello World!"); |
| 25 | 25 | ||
| 26 | let mut p = embassy_stm32::init(Default::default()); | 26 | let mut p = embassy_stm32::init(Default::default()); |
| @@ -34,9 +34,12 @@ fn main() -> ! { | |||
| 34 | 34 | ||
| 35 | let mut can = Can::new(p.CAN1, p.PA11, p.PA12, Irqs); | 35 | let mut can = Can::new(p.CAN1, p.PA11, p.PA12, Irqs); |
| 36 | 36 | ||
| 37 | can.modify_filters().enable_bank(0, Fifo::Fifo0, Mask32::accept_all()); | 37 | can.as_mut() |
| 38 | .modify_filters() | ||
| 39 | .enable_bank(0, Fifo::Fifo0, Mask32::accept_all()); | ||
| 38 | 40 | ||
| 39 | can.modify_config() | 41 | can.as_mut() |
| 42 | .modify_config() | ||
| 40 | .set_bit_timing(0x001c0003) // http://www.bittiming.can-wiki.info/ | 43 | .set_bit_timing(0x001c0003) // http://www.bittiming.can-wiki.info/ |
| 41 | .set_loopback(true) // Receive own frames | 44 | .set_loopback(true) // Receive own frames |
| 42 | .set_silent(true) | 45 | .set_silent(true) |
| @@ -45,9 +48,8 @@ fn main() -> ! { | |||
| 45 | let mut i: u8 = 0; | 48 | let mut i: u8 = 0; |
| 46 | loop { | 49 | loop { |
| 47 | let tx_frame = Frame::new_data(unwrap!(StandardId::new(i as _)), [i]); | 50 | let tx_frame = Frame::new_data(unwrap!(StandardId::new(i as _)), [i]); |
| 48 | unwrap!(nb::block!(can.transmit(&tx_frame))); | 51 | can.write(&tx_frame).await; |
| 49 | while !can.is_transmitter_idle() {} | 52 | let (_, rx_frame) = can.read().await.unwrap(); |
| 50 | let rx_frame = unwrap!(nb::block!(can.receive())); | ||
| 51 | info!("loopback frame {=u8}", unwrap!(rx_frame.data())[0]); | 53 | info!("loopback frame {=u8}", unwrap!(rx_frame.data())[0]); |
| 52 | i += 1; | 54 | i += 1; |
| 53 | } | 55 | } |
diff --git a/examples/stm32f4/src/bin/eth.rs b/examples/stm32f4/src/bin/eth.rs new file mode 100644 index 000000000..d0b164393 --- /dev/null +++ b/examples/stm32f4/src/bin/eth.rs | |||
| @@ -0,0 +1,111 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | #![feature(type_alias_impl_trait)] | ||
| 4 | |||
| 5 | use defmt::*; | ||
| 6 | use embassy_executor::Spawner; | ||
| 7 | use embassy_net::tcp::TcpSocket; | ||
| 8 | use embassy_net::{Ipv4Address, Stack, StackResources}; | ||
| 9 | use embassy_stm32::eth::generic_smi::GenericSMI; | ||
| 10 | use embassy_stm32::eth::{Ethernet, PacketQueue}; | ||
| 11 | use embassy_stm32::peripherals::ETH; | ||
| 12 | use embassy_stm32::rng::Rng; | ||
| 13 | use embassy_stm32::time::mhz; | ||
| 14 | use embassy_stm32::{bind_interrupts, eth, Config}; | ||
| 15 | use embassy_time::{Duration, Timer}; | ||
| 16 | use embedded_io::asynch::Write; | ||
| 17 | use static_cell::make_static; | ||
| 18 | use {defmt_rtt as _, panic_probe as _}; | ||
| 19 | bind_interrupts!(struct Irqs { | ||
| 20 | ETH => eth::InterruptHandler; | ||
| 21 | }); | ||
| 22 | |||
| 23 | type Device = Ethernet<'static, ETH, GenericSMI>; | ||
| 24 | |||
| 25 | #[embassy_executor::task] | ||
| 26 | async fn net_task(stack: &'static Stack<Device>) -> ! { | ||
| 27 | stack.run().await | ||
| 28 | } | ||
| 29 | |||
| 30 | #[embassy_executor::main] | ||
| 31 | async fn main(spawner: Spawner) -> ! { | ||
| 32 | let mut config = Config::default(); | ||
| 33 | config.rcc.sys_ck = Some(mhz(200)); | ||
| 34 | let p = embassy_stm32::init(config); | ||
| 35 | |||
| 36 | info!("Hello World!"); | ||
| 37 | |||
| 38 | // Generate random seed. | ||
| 39 | let mut rng = Rng::new(p.RNG); | ||
| 40 | let mut seed = [0; 8]; | ||
| 41 | let _ = rng.async_fill_bytes(&mut seed).await; | ||
| 42 | let seed = u64::from_le_bytes(seed); | ||
| 43 | |||
| 44 | let mac_addr = [0x00, 0x00, 0xDE, 0xAD, 0xBE, 0xEF]; | ||
| 45 | |||
| 46 | let device = Ethernet::new( | ||
| 47 | make_static!(PacketQueue::<16, 16>::new()), | ||
| 48 | p.ETH, | ||
| 49 | Irqs, | ||
| 50 | p.PA1, | ||
| 51 | p.PA2, | ||
| 52 | p.PC1, | ||
| 53 | p.PA7, | ||
| 54 | p.PC4, | ||
| 55 | p.PC5, | ||
| 56 | p.PG13, | ||
| 57 | p.PB13, | ||
| 58 | p.PG11, | ||
| 59 | GenericSMI::new(), | ||
| 60 | mac_addr, | ||
| 61 | 0, | ||
| 62 | ); | ||
| 63 | |||
| 64 | let config = embassy_net::Config::dhcpv4(Default::default()); | ||
| 65 | //let config = embassy_net::Config::ipv4_static(embassy_net::StaticConfigV4 { | ||
| 66 | // address: Ipv4Cidr::new(Ipv4Address::new(10, 42, 0, 61), 24), | ||
| 67 | // dns_servers: Vec::new(), | ||
| 68 | // gateway: Some(Ipv4Address::new(10, 42, 0, 1)), | ||
| 69 | //}); | ||
| 70 | |||
| 71 | // Init network stack | ||
| 72 | let stack = &*make_static!(Stack::new( | ||
| 73 | device, | ||
| 74 | config, | ||
| 75 | make_static!(StackResources::<2>::new()), | ||
| 76 | seed | ||
| 77 | )); | ||
| 78 | |||
| 79 | // Launch network task | ||
| 80 | unwrap!(spawner.spawn(net_task(&stack))); | ||
| 81 | |||
| 82 | info!("Network task initialized"); | ||
| 83 | |||
| 84 | // Then we can use it! | ||
| 85 | let mut rx_buffer = [0; 4096]; | ||
| 86 | let mut tx_buffer = [0; 4096]; | ||
| 87 | |||
| 88 | loop { | ||
| 89 | let mut socket = TcpSocket::new(&stack, &mut rx_buffer, &mut tx_buffer); | ||
| 90 | |||
| 91 | socket.set_timeout(Some(embassy_time::Duration::from_secs(10))); | ||
| 92 | |||
| 93 | let remote_endpoint = (Ipv4Address::new(10, 42, 0, 1), 8000); | ||
| 94 | info!("connecting..."); | ||
| 95 | let r = socket.connect(remote_endpoint).await; | ||
| 96 | if let Err(e) = r { | ||
| 97 | info!("connect error: {:?}", e); | ||
| 98 | continue; | ||
| 99 | } | ||
| 100 | info!("connected!"); | ||
| 101 | let buf = [0; 1024]; | ||
| 102 | loop { | ||
| 103 | let r = socket.write_all(&buf).await; | ||
| 104 | if let Err(e) = r { | ||
| 105 | info!("write error: {:?}", e); | ||
| 106 | continue; | ||
| 107 | } | ||
| 108 | Timer::after(Duration::from_secs(1)).await; | ||
| 109 | } | ||
| 110 | } | ||
| 111 | } | ||
diff --git a/examples/stm32f7/Cargo.toml b/examples/stm32f7/Cargo.toml index 657251c50..84d7b79c5 100644 --- a/examples/stm32f7/Cargo.toml +++ b/examples/stm32f7/Cargo.toml | |||
| @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" | |||
| 7 | [dependencies] | 7 | [dependencies] |
| 8 | embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] } | 8 | embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] } |
| 9 | embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } | 9 | embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } |
| 10 | embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } | 10 | embassy-time = { version = "0.1.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } |
| 11 | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32f767zi", "unstable-pac", "time-driver-any", "exti"] } | 11 | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32f767zi", "unstable-pac", "time-driver-any", "exti"] } |
| 12 | embassy-net = { path = "../../embassy-net", features = ["defmt", "nightly", "tcp", "dhcpv4", "medium-ethernet"] } | 12 | embassy-net = { path = "../../embassy-net", features = ["defmt", "nightly", "tcp", "dhcpv4", "medium-ethernet"] } |
| 13 | embedded-io = { version = "0.4.0", features = ["async"] } | 13 | embedded-io = { version = "0.4.0", features = ["async"] } |
diff --git a/examples/stm32f7/src/bin/can.rs b/examples/stm32f7/src/bin/can.rs new file mode 100644 index 000000000..1b5b377ea --- /dev/null +++ b/examples/stm32f7/src/bin/can.rs | |||
| @@ -0,0 +1,66 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | #![feature(type_alias_impl_trait)] | ||
| 4 | |||
| 5 | use defmt::*; | ||
| 6 | use embassy_executor::Spawner; | ||
| 7 | use embassy_stm32::bind_interrupts; | ||
| 8 | use embassy_stm32::can::bxcan::filter::Mask32; | ||
| 9 | use embassy_stm32::can::bxcan::{Fifo, Frame, StandardId}; | ||
| 10 | use embassy_stm32::can::{ | ||
| 11 | Can, CanTx, Rx0InterruptHandler, Rx1InterruptHandler, SceInterruptHandler, TxInterruptHandler, | ||
| 12 | }; | ||
| 13 | use embassy_stm32::gpio::{Input, Pull}; | ||
| 14 | use embassy_stm32::peripherals::CAN3; | ||
| 15 | use {defmt_rtt as _, panic_probe as _}; | ||
| 16 | |||
| 17 | bind_interrupts!(struct Irqs { | ||
| 18 | CAN3_RX0 => Rx0InterruptHandler<CAN3>; | ||
| 19 | CAN3_RX1 => Rx1InterruptHandler<CAN3>; | ||
| 20 | CAN3_SCE => SceInterruptHandler<CAN3>; | ||
| 21 | CAN3_TX => TxInterruptHandler<CAN3>; | ||
| 22 | }); | ||
| 23 | |||
| 24 | #[embassy_executor::task] | ||
| 25 | pub async fn send_can_message(tx: &'static mut CanTx<'static, 'static, CAN3>) { | ||
| 26 | loop { | ||
| 27 | let frame = Frame::new_data(unwrap!(StandardId::new(0 as _)), [0]); | ||
| 28 | tx.write(&frame).await; | ||
| 29 | embassy_time::Timer::after(embassy_time::Duration::from_secs(1)).await; | ||
| 30 | } | ||
| 31 | } | ||
| 32 | |||
| 33 | #[embassy_executor::main] | ||
| 34 | async fn main(spawner: Spawner) { | ||
| 35 | info!("Hello World!"); | ||
| 36 | |||
| 37 | let mut p = embassy_stm32::init(Default::default()); | ||
| 38 | |||
| 39 | // The next two lines are a workaround for testing without transceiver. | ||
| 40 | // To synchronise to the bus the RX input needs to see a high level. | ||
| 41 | // Use `mem::forget()` to release the borrow on the pin but keep the | ||
| 42 | // pull-up resistor enabled. | ||
| 43 | let rx_pin = Input::new(&mut p.PA15, Pull::Up); | ||
| 44 | core::mem::forget(rx_pin); | ||
| 45 | |||
| 46 | let can: &'static mut Can<'static, CAN3> = static_cell::make_static!(Can::new(p.CAN3, p.PA8, p.PA15, Irqs)); | ||
| 47 | can.as_mut() | ||
| 48 | .modify_filters() | ||
| 49 | .enable_bank(0, Fifo::Fifo0, Mask32::accept_all()); | ||
| 50 | |||
| 51 | can.as_mut() | ||
| 52 | .modify_config() | ||
| 53 | .set_bit_timing(0x001c0001) // http://www.bittiming.can-wiki.info/ | ||
| 54 | .set_loopback(true) | ||
| 55 | .enable(); | ||
| 56 | |||
| 57 | let (tx, mut rx) = can.split(); | ||
| 58 | |||
| 59 | let tx: &'static mut CanTx<'static, 'static, CAN3> = static_cell::make_static!(tx); | ||
| 60 | spawner.spawn(send_can_message(tx)).unwrap(); | ||
| 61 | |||
| 62 | loop { | ||
| 63 | let frame = rx.read().await.unwrap(); | ||
| 64 | println!("Received: {:?}", frame); | ||
| 65 | } | ||
| 66 | } | ||
diff --git a/examples/stm32f7/src/bin/eth.rs b/examples/stm32f7/src/bin/eth.rs index fde6a7576..c6b2ba45c 100644 --- a/examples/stm32f7/src/bin/eth.rs +++ b/examples/stm32f7/src/bin/eth.rs | |||
| @@ -57,7 +57,7 @@ async fn main(spawner: Spawner) -> ! { | |||
| 57 | p.PG13, | 57 | p.PG13, |
| 58 | p.PB13, | 58 | p.PB13, |
| 59 | p.PG11, | 59 | p.PG11, |
| 60 | GenericSMI, | 60 | GenericSMI::new(), |
| 61 | mac_addr, | 61 | mac_addr, |
| 62 | 0, | 62 | 0, |
| 63 | ); | 63 | ); |
diff --git a/examples/stm32g0/Cargo.toml b/examples/stm32g0/Cargo.toml index c5245757b..c88282d91 100644 --- a/examples/stm32g0/Cargo.toml +++ b/examples/stm32g0/Cargo.toml | |||
| @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" | |||
| 7 | [dependencies] | 7 | [dependencies] |
| 8 | embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] } | 8 | embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] } |
| 9 | embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } | 9 | embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } |
| 10 | embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } | 10 | embassy-time = { version = "0.1.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } |
| 11 | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "time-driver-any", "stm32g071rb", "memory-x", "unstable-pac", "exti"] } | 11 | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "time-driver-any", "stm32g071rb", "memory-x", "unstable-pac", "exti"] } |
| 12 | 12 | ||
| 13 | defmt = "0.3" | 13 | defmt = "0.3" |
diff --git a/examples/stm32g4/Cargo.toml b/examples/stm32g4/Cargo.toml index fbfbc6408..18bd03c39 100644 --- a/examples/stm32g4/Cargo.toml +++ b/examples/stm32g4/Cargo.toml | |||
| @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" | |||
| 7 | [dependencies] | 7 | [dependencies] |
| 8 | embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] } | 8 | embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] } |
| 9 | embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } | 9 | embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } |
| 10 | embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } | 10 | embassy-time = { version = "0.1.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } |
| 11 | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "time-driver-any", "stm32g491re", "memory-x", "unstable-pac", "exti"] } | 11 | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "time-driver-any", "stm32g491re", "memory-x", "unstable-pac", "exti"] } |
| 12 | embassy-hal-common = {version = "0.1.0", path = "../../embassy-hal-common" } | 12 | embassy-hal-common = {version = "0.1.0", path = "../../embassy-hal-common" } |
| 13 | embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] } | 13 | embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] } |
diff --git a/examples/stm32h5/Cargo.toml b/examples/stm32h5/Cargo.toml index ebe511347..227bc28b4 100644 --- a/examples/stm32h5/Cargo.toml +++ b/examples/stm32h5/Cargo.toml | |||
| @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" | |||
| 7 | [dependencies] | 7 | [dependencies] |
| 8 | embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] } | 8 | embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] } |
| 9 | embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } | 9 | embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } |
| 10 | embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "unstable-traits", "tick-hz-32_768"] } | 10 | embassy-time = { version = "0.1.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "unstable-traits", "tick-hz-32_768"] } |
| 11 | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32h563zi", "time-driver-any", "exti", "unstable-pac", "unstable-traits"] } | 11 | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32h563zi", "time-driver-any", "exti", "unstable-pac", "unstable-traits"] } |
| 12 | embassy-net = { path = "../../embassy-net", features = ["defmt", "nightly", "tcp", "dhcpv4", "medium-ethernet", "unstable-traits", "proto-ipv6"] } | 12 | embassy-net = { path = "../../embassy-net", features = ["defmt", "nightly", "tcp", "dhcpv4", "medium-ethernet", "unstable-traits", "proto-ipv6"] } |
| 13 | embedded-io = { version = "0.4.0", features = ["async"] } | 13 | embedded-io = { version = "0.4.0", features = ["async"] } |
| @@ -19,8 +19,8 @@ defmt-rtt = "0.4" | |||
| 19 | cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } | 19 | cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } |
| 20 | cortex-m-rt = "0.7.0" | 20 | cortex-m-rt = "0.7.0" |
| 21 | embedded-hal = "0.2.6" | 21 | embedded-hal = "0.2.6" |
| 22 | embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-alpha.10" } | 22 | embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-alpha.11" } |
| 23 | embedded-hal-async = { version = "=0.2.0-alpha.1" } | 23 | embedded-hal-async = { version = "=0.2.0-alpha.2" } |
| 24 | embedded-nal-async = "0.4.0" | 24 | embedded-nal-async = "0.4.0" |
| 25 | panic-probe = { version = "0.3", features = ["print-defmt"] } | 25 | panic-probe = { version = "0.3", features = ["print-defmt"] } |
| 26 | futures = { version = "0.3.17", default-features = false, features = ["async-await"] } | 26 | futures = { version = "0.3.17", default-features = false, features = ["async-await"] } |
diff --git a/examples/stm32h5/src/bin/eth.rs b/examples/stm32h5/src/bin/eth.rs index 78c8282a6..0bff85ed8 100644 --- a/examples/stm32h5/src/bin/eth.rs +++ b/examples/stm32h5/src/bin/eth.rs | |||
| @@ -76,7 +76,7 @@ async fn main(spawner: Spawner) -> ! { | |||
| 76 | p.PG13, | 76 | p.PG13, |
| 77 | p.PB15, | 77 | p.PB15, |
| 78 | p.PG11, | 78 | p.PG11, |
| 79 | GenericSMI, | 79 | GenericSMI::new(), |
| 80 | mac_addr, | 80 | mac_addr, |
| 81 | 0, | 81 | 0, |
| 82 | ); | 82 | ); |
diff --git a/examples/stm32h7/Cargo.toml b/examples/stm32h7/Cargo.toml index 62ef5e9e4..768702fa9 100644 --- a/examples/stm32h7/Cargo.toml +++ b/examples/stm32h7/Cargo.toml | |||
| @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" | |||
| 7 | [dependencies] | 7 | [dependencies] |
| 8 | embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] } | 8 | embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] } |
| 9 | embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } | 9 | embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } |
| 10 | embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "unstable-traits", "tick-hz-32_768"] } | 10 | embassy-time = { version = "0.1.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "unstable-traits", "tick-hz-32_768"] } |
| 11 | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32h743bi", "time-driver-any", "exti", "unstable-pac", "unstable-traits"] } | 11 | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32h743bi", "time-driver-any", "exti", "unstable-pac", "unstable-traits"] } |
| 12 | embassy-net = { path = "../../embassy-net", features = ["defmt", "nightly", "tcp", "dhcpv4", "medium-ethernet", "unstable-traits", "proto-ipv6"] } | 12 | embassy-net = { path = "../../embassy-net", features = ["defmt", "nightly", "tcp", "dhcpv4", "medium-ethernet", "unstable-traits", "proto-ipv6"] } |
| 13 | embedded-io = { version = "0.4.0", features = ["async"] } | 13 | embedded-io = { version = "0.4.0", features = ["async"] } |
| @@ -19,8 +19,8 @@ defmt-rtt = "0.4" | |||
| 19 | cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } | 19 | cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } |
| 20 | cortex-m-rt = "0.7.0" | 20 | cortex-m-rt = "0.7.0" |
| 21 | embedded-hal = "0.2.6" | 21 | embedded-hal = "0.2.6" |
| 22 | embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-alpha.10" } | 22 | embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-alpha.11" } |
| 23 | embedded-hal-async = { version = "=0.2.0-alpha.1" } | 23 | embedded-hal-async = { version = "=0.2.0-alpha.2" } |
| 24 | embedded-nal-async = "0.4.0" | 24 | embedded-nal-async = "0.4.0" |
| 25 | panic-probe = { version = "0.3", features = ["print-defmt"] } | 25 | panic-probe = { version = "0.3", features = ["print-defmt"] } |
| 26 | futures = { version = "0.3.17", default-features = false, features = ["async-await"] } | 26 | futures = { version = "0.3.17", default-features = false, features = ["async-await"] } |
diff --git a/examples/stm32h7/src/bin/eth.rs b/examples/stm32h7/src/bin/eth.rs index 12d37f7a4..cfafcaed1 100644 --- a/examples/stm32h7/src/bin/eth.rs +++ b/examples/stm32h7/src/bin/eth.rs | |||
| @@ -58,7 +58,7 @@ async fn main(spawner: Spawner) -> ! { | |||
| 58 | p.PG13, | 58 | p.PG13, |
| 59 | p.PB13, | 59 | p.PB13, |
| 60 | p.PG11, | 60 | p.PG11, |
| 61 | GenericSMI, | 61 | GenericSMI::new(), |
| 62 | mac_addr, | 62 | mac_addr, |
| 63 | 0, | 63 | 0, |
| 64 | ); | 64 | ); |
diff --git a/examples/stm32h7/src/bin/eth_client.rs b/examples/stm32h7/src/bin/eth_client.rs index 6078fc3fe..4ed737578 100644 --- a/examples/stm32h7/src/bin/eth_client.rs +++ b/examples/stm32h7/src/bin/eth_client.rs | |||
| @@ -59,7 +59,7 @@ async fn main(spawner: Spawner) -> ! { | |||
| 59 | p.PG13, | 59 | p.PG13, |
| 60 | p.PB13, | 60 | p.PB13, |
| 61 | p.PG11, | 61 | p.PG11, |
| 62 | GenericSMI, | 62 | GenericSMI::new(), |
| 63 | mac_addr, | 63 | mac_addr, |
| 64 | 0, | 64 | 0, |
| 65 | ); | 65 | ); |
diff --git a/examples/stm32l0/Cargo.toml b/examples/stm32l0/Cargo.toml index 2ead714e4..747cec7bf 100644 --- a/examples/stm32l0/Cargo.toml +++ b/examples/stm32l0/Cargo.toml | |||
| @@ -12,7 +12,7 @@ nightly = ["embassy-stm32/nightly", "embassy-time/nightly", "embassy-time/unstab | |||
| 12 | [dependencies] | 12 | [dependencies] |
| 13 | embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] } | 13 | embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] } |
| 14 | embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } | 14 | embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } |
| 15 | embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } | 15 | embassy-time = { version = "0.1.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } |
| 16 | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["defmt", "stm32l072cz", "time-driver-any", "exti", "unstable-traits", "memory-x"] } | 16 | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["defmt", "stm32l072cz", "time-driver-any", "exti", "unstable-traits", "memory-x"] } |
| 17 | embassy-lora = { version = "0.1.0", path = "../../embassy-lora", features = ["time", "defmt"], optional = true } | 17 | embassy-lora = { version = "0.1.0", path = "../../embassy-lora", features = ["time", "defmt"], optional = true } |
| 18 | lora-phy = { version = "1", optional = true } | 18 | lora-phy = { version = "1", optional = true } |
| @@ -32,3 +32,6 @@ futures = { version = "0.3.17", default-features = false, features = ["async-awa | |||
| 32 | heapless = { version = "0.7.5", default-features = false } | 32 | heapless = { version = "0.7.5", default-features = false } |
| 33 | embedded-hal = "0.2.6" | 33 | embedded-hal = "0.2.6" |
| 34 | static_cell = "1.1" | 34 | static_cell = "1.1" |
| 35 | |||
| 36 | [patch.crates-io] | ||
| 37 | lora-phy = { git = "https://github.com/embassy-rs/lora-phy", rev = "ad289428fd44b02788e2fa2116445cc8f640a265" } | ||
diff --git a/examples/stm32l1/Cargo.toml b/examples/stm32l1/Cargo.toml index 93d48abeb..dcca1cc3d 100644 --- a/examples/stm32l1/Cargo.toml +++ b/examples/stm32l1/Cargo.toml | |||
| @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" | |||
| 7 | [dependencies] | 7 | [dependencies] |
| 8 | embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] } | 8 | embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] } |
| 9 | embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } | 9 | embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } |
| 10 | embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } | 10 | embassy-time = { version = "0.1.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } |
| 11 | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32l151cb-a", "time-driver-any", "memory-x"] } | 11 | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32l151cb-a", "time-driver-any", "memory-x"] } |
| 12 | 12 | ||
| 13 | defmt = "0.3" | 13 | defmt = "0.3" |
diff --git a/examples/stm32l4/Cargo.toml b/examples/stm32l4/Cargo.toml index 3bb473ef5..c55558518 100644 --- a/examples/stm32l4/Cargo.toml +++ b/examples/stm32l4/Cargo.toml | |||
| @@ -7,9 +7,9 @@ license = "MIT OR Apache-2.0" | |||
| 7 | [dependencies] | 7 | [dependencies] |
| 8 | embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] } | 8 | embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] } |
| 9 | embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } | 9 | embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } |
| 10 | embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } | 10 | embassy-time = { version = "0.1.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } |
| 11 | embassy-embedded-hal = { version = "0.1.0", path = "../../embassy-embedded-hal" } | 11 | embassy-embedded-hal = { version = "0.1.0", path = "../../embassy-embedded-hal" } |
| 12 | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "unstable-pac", "stm32l4s5vi", "time-driver-any", "exti", "unstable-traits"] } | 12 | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "unstable-pac", "stm32l4s5vi", "time-driver-any", "exti", "unstable-traits", "chrono"] } |
| 13 | embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] } | 13 | embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] } |
| 14 | 14 | ||
| 15 | defmt = "0.3" | 15 | defmt = "0.3" |
| @@ -18,10 +18,11 @@ defmt-rtt = "0.4" | |||
| 18 | cortex-m = { version = "0.7.6", features = ["critical-section-single-core"] } | 18 | cortex-m = { version = "0.7.6", features = ["critical-section-single-core"] } |
| 19 | cortex-m-rt = "0.7.0" | 19 | cortex-m-rt = "0.7.0" |
| 20 | embedded-hal = "0.2.6" | 20 | embedded-hal = "0.2.6" |
| 21 | embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-alpha.10" } | 21 | embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-alpha.11" } |
| 22 | embedded-hal-async = { version = "=0.2.0-alpha.1" } | 22 | embedded-hal-async = { version = "=0.2.0-alpha.2" } |
| 23 | panic-probe = { version = "0.3", features = ["print-defmt"] } | 23 | panic-probe = { version = "0.3", features = ["print-defmt"] } |
| 24 | futures = { version = "0.3.17", default-features = false, features = ["async-await"] } | 24 | futures = { version = "0.3.17", default-features = false, features = ["async-await"] } |
| 25 | heapless = { version = "0.7.5", default-features = false } | 25 | heapless = { version = "0.7.5", default-features = false } |
| 26 | chrono = { version = "^0.4", default-features = false } | ||
| 26 | 27 | ||
| 27 | micromath = "2.0.0" | 28 | micromath = "2.0.0" |
diff --git a/examples/stm32l4/src/bin/rtc.rs b/examples/stm32l4/src/bin/rtc.rs new file mode 100644 index 000000000..d72d5ddb6 --- /dev/null +++ b/examples/stm32l4/src/bin/rtc.rs | |||
| @@ -0,0 +1,49 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | #![feature(type_alias_impl_trait)] | ||
| 4 | |||
| 5 | use chrono::{NaiveDate, NaiveDateTime}; | ||
| 6 | use defmt::*; | ||
| 7 | use embassy_executor::Spawner; | ||
| 8 | use embassy_stm32::rcc::{self, ClockSrc, PLLClkDiv, PLLMul, PLLSource, PLLSrcDiv}; | ||
| 9 | use embassy_stm32::rtc::{Rtc, RtcConfig}; | ||
| 10 | use embassy_stm32::time::Hertz; | ||
| 11 | use embassy_stm32::Config; | ||
| 12 | use embassy_time::{Duration, Timer}; | ||
| 13 | use {defmt_rtt as _, panic_probe as _}; | ||
| 14 | |||
| 15 | #[embassy_executor::main] | ||
| 16 | async fn main(_spawner: Spawner) { | ||
| 17 | let p = { | ||
| 18 | let mut config = Config::default(); | ||
| 19 | config.rcc.mux = ClockSrc::PLL( | ||
| 20 | PLLSource::HSE(Hertz::mhz(8)), | ||
| 21 | PLLClkDiv::Div2, | ||
| 22 | PLLSrcDiv::Div1, | ||
| 23 | PLLMul::Mul20, | ||
| 24 | None, | ||
| 25 | ); | ||
| 26 | config.rcc.rtc_mux = rcc::RtcClockSource::LSE32; | ||
| 27 | embassy_stm32::init(config) | ||
| 28 | }; | ||
| 29 | info!("Hello World!"); | ||
| 30 | |||
| 31 | let now = NaiveDate::from_ymd_opt(2020, 5, 15) | ||
| 32 | .unwrap() | ||
| 33 | .and_hms_opt(10, 30, 15) | ||
| 34 | .unwrap(); | ||
| 35 | |||
| 36 | let mut rtc = Rtc::new( | ||
| 37 | p.RTC, | ||
| 38 | RtcConfig::default().clock_config(embassy_stm32::rtc::RtcClockSource::LSE), | ||
| 39 | ); | ||
| 40 | info!("Got RTC! {:?}", now.timestamp()); | ||
| 41 | |||
| 42 | rtc.set_datetime(now.into()).expect("datetime not set"); | ||
| 43 | |||
| 44 | // In reality the delay would be much longer | ||
| 45 | Timer::after(Duration::from_millis(20000)).await; | ||
| 46 | |||
| 47 | let then: NaiveDateTime = rtc.now().unwrap().into(); | ||
| 48 | info!("Got RTC! {:?}", then.timestamp()); | ||
| 49 | } | ||
diff --git a/examples/stm32l5/Cargo.toml b/examples/stm32l5/Cargo.toml index 6035c291f..54911482e 100644 --- a/examples/stm32l5/Cargo.toml +++ b/examples/stm32l5/Cargo.toml | |||
| @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" | |||
| 7 | [dependencies] | 7 | [dependencies] |
| 8 | embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] } | 8 | embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] } |
| 9 | embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } | 9 | embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } |
| 10 | embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } | 10 | embassy-time = { version = "0.1.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } |
| 11 | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "unstable-pac", "stm32l552ze", "time-driver-any", "exti", "unstable-traits", "memory-x"] } | 11 | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "unstable-pac", "stm32l552ze", "time-driver-any", "exti", "unstable-traits", "memory-x"] } |
| 12 | embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] } | 12 | embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] } |
| 13 | embassy-net = { version = "0.1.0", path = "../../embassy-net", features = ["defmt", "nightly", "tcp", "dhcpv4", "medium-ethernet"] } | 13 | embassy-net = { version = "0.1.0", path = "../../embassy-net", features = ["defmt", "nightly", "tcp", "dhcpv4", "medium-ethernet"] } |
diff --git a/examples/stm32u5/Cargo.toml b/examples/stm32u5/Cargo.toml index e2318c3d6..835e32940 100644 --- a/examples/stm32u5/Cargo.toml +++ b/examples/stm32u5/Cargo.toml | |||
| @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" | |||
| 7 | [dependencies] | 7 | [dependencies] |
| 8 | embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] } | 8 | embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] } |
| 9 | embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } | 9 | embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } |
| 10 | embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } | 10 | embassy-time = { version = "0.1.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } |
| 11 | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "unstable-pac", "stm32u585ai", "time-driver-any", "memory-x" ] } | 11 | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "unstable-pac", "stm32u585ai", "time-driver-any", "memory-x" ] } |
| 12 | embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] } | 12 | embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] } |
| 13 | 13 | ||
diff --git a/examples/stm32wb/.cargo/config.toml b/examples/stm32wb/.cargo/config.toml index 8b6d6d754..51c499ee7 100644 --- a/examples/stm32wb/.cargo/config.toml +++ b/examples/stm32wb/.cargo/config.toml | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | [target.'cfg(all(target_arch = "arm", target_os = "none"))'] | 1 | [target.'cfg(all(target_arch = "arm", target_os = "none"))'] |
| 2 | # replace STM32WB55CCUx with your chip as listed in `probe-rs chip list` | 2 | # replace STM32WB55CCUx with your chip as listed in `probe-rs chip list` |
| 3 | # runner = "probe-rs run --chip STM32WB55RGVx --speed 1000 --connect-under-reset" | 3 | # runner = "probe-run --chip STM32WB55RGVx --speed 1000 --connect-under-reset" |
| 4 | runner = "teleprobe local run --chip STM32WB55RG --elf" | 4 | runner = "teleprobe local run --chip STM32WB55RG --elf" |
| 5 | 5 | ||
| 6 | [build] | 6 | [build] |
diff --git a/examples/stm32wb/Cargo.toml b/examples/stm32wb/Cargo.toml index fbb2d918b..becf2d3fb 100644 --- a/examples/stm32wb/Cargo.toml +++ b/examples/stm32wb/Cargo.toml | |||
| @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" | |||
| 7 | [dependencies] | 7 | [dependencies] |
| 8 | embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] } | 8 | embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] } |
| 9 | embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } | 9 | embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } |
| 10 | embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } | 10 | embassy-time = { version = "0.1.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } |
| 11 | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32wb55rg", "time-driver-any", "memory-x", "exti"] } | 11 | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32wb55rg", "time-driver-any", "memory-x", "exti"] } |
| 12 | embassy-stm32-wpan = { version = "0.1.0", path = "../../embassy-stm32-wpan", features = ["defmt", "stm32wb55rg"] } | 12 | embassy-stm32-wpan = { version = "0.1.0", path = "../../embassy-stm32-wpan", features = ["defmt", "stm32wb55rg"] } |
| 13 | 13 | ||
| @@ -23,7 +23,7 @@ heapless = { version = "0.7.5", default-features = false } | |||
| 23 | 23 | ||
| 24 | 24 | ||
| 25 | [features] | 25 | [features] |
| 26 | default = ["ble"] | 26 | default = ["ble", "mac"] |
| 27 | mac = ["embassy-stm32-wpan/mac"] | 27 | mac = ["embassy-stm32-wpan/mac"] |
| 28 | ble = ["embassy-stm32-wpan/ble"] | 28 | ble = ["embassy-stm32-wpan/ble"] |
| 29 | 29 | ||
| @@ -36,8 +36,13 @@ name = "tl_mbox_mac" | |||
| 36 | required-features = ["mac"] | 36 | required-features = ["mac"] |
| 37 | 37 | ||
| 38 | [[bin]] | 38 | [[bin]] |
| 39 | name = "mac_ffd" | ||
| 40 | required-features = ["mac"] | ||
| 41 | |||
| 42 | [[bin]] | ||
| 39 | name = "eddystone_beacon" | 43 | name = "eddystone_beacon" |
| 40 | required-features = ["ble"] | 44 | required-features = ["ble"] |
| 41 | 45 | ||
| 42 | [patch.crates-io] | 46 | [[bin]] |
| 43 | stm32wb-hci = { git = "https://github.com/OueslatiGhaith/stm32wb-hci", rev = "9f663be"} \ No newline at end of file | 47 | name = "gatt_server" |
| 48 | required-features = ["ble"] \ No newline at end of file | ||
diff --git a/examples/stm32wb/src/bin/eddystone_beacon.rs b/examples/stm32wb/src/bin/eddystone_beacon.rs index b99f8cb2e..451bd7d29 100644 --- a/examples/stm32wb/src/bin/eddystone_beacon.rs +++ b/examples/stm32wb/src/bin/eddystone_beacon.rs | |||
| @@ -63,7 +63,7 @@ async fn main(_spawner: Spawner) { | |||
| 63 | let sys_event = mbox.sys_subsystem.read().await; | 63 | let sys_event = mbox.sys_subsystem.read().await; |
| 64 | info!("sys event: {}", sys_event.payload()); | 64 | info!("sys event: {}", sys_event.payload()); |
| 65 | 65 | ||
| 66 | mbox.sys_subsystem.shci_c2_ble_init(Default::default()).await; | 66 | let _ = mbox.sys_subsystem.shci_c2_ble_init(Default::default()).await; |
| 67 | 67 | ||
| 68 | info!("resetting BLE..."); | 68 | info!("resetting BLE..."); |
| 69 | mbox.ble_subsystem.reset().await; | 69 | mbox.ble_subsystem.reset().await; |
diff --git a/examples/stm32wb/src/bin/gatt_server.rs b/examples/stm32wb/src/bin/gatt_server.rs new file mode 100644 index 000000000..0f6419d45 --- /dev/null +++ b/examples/stm32wb/src/bin/gatt_server.rs | |||
| @@ -0,0 +1,397 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | #![feature(type_alias_impl_trait)] | ||
| 4 | |||
| 5 | use core::time::Duration; | ||
| 6 | |||
| 7 | use defmt::*; | ||
| 8 | use embassy_executor::Spawner; | ||
| 9 | use embassy_stm32::bind_interrupts; | ||
| 10 | use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler}; | ||
| 11 | use embassy_stm32_wpan::hci::event::command::{CommandComplete, ReturnParameters}; | ||
| 12 | use embassy_stm32_wpan::hci::host::uart::{Packet, UartHci}; | ||
| 13 | use embassy_stm32_wpan::hci::host::{AdvertisingFilterPolicy, EncryptionKey, HostHci, OwnAddressType}; | ||
| 14 | use embassy_stm32_wpan::hci::types::AdvertisingType; | ||
| 15 | use embassy_stm32_wpan::hci::vendor::stm32wb::command::gap::{ | ||
| 16 | AddressType, AuthenticationRequirements, DiscoverableParameters, GapCommands, IoCapability, LocalName, Pin, Role, | ||
| 17 | SecureConnectionSupport, | ||
| 18 | }; | ||
| 19 | use embassy_stm32_wpan::hci::vendor::stm32wb::command::gatt::{ | ||
| 20 | AddCharacteristicParameters, AddServiceParameters, CharacteristicEvent, CharacteristicPermission, | ||
| 21 | CharacteristicProperty, EncryptionKeySize, GattCommands, ServiceType, UpdateCharacteristicValueParameters, Uuid, | ||
| 22 | WriteResponseParameters, | ||
| 23 | }; | ||
| 24 | use embassy_stm32_wpan::hci::vendor::stm32wb::command::hal::{ConfigData, HalCommands, PowerLevel}; | ||
| 25 | use embassy_stm32_wpan::hci::vendor::stm32wb::event::{self, AttributeHandle, Stm32Wb5xEvent}; | ||
| 26 | use embassy_stm32_wpan::hci::{BdAddr, Event}; | ||
| 27 | use embassy_stm32_wpan::lhci::LhciC1DeviceInformationCcrp; | ||
| 28 | use embassy_stm32_wpan::sub::ble::Ble; | ||
| 29 | use embassy_stm32_wpan::TlMbox; | ||
| 30 | use {defmt_rtt as _, panic_probe as _}; | ||
| 31 | |||
| 32 | bind_interrupts!(struct Irqs{ | ||
| 33 | IPCC_C1_RX => ReceiveInterruptHandler; | ||
| 34 | IPCC_C1_TX => TransmitInterruptHandler; | ||
| 35 | }); | ||
| 36 | |||
| 37 | const BLE_GAP_DEVICE_NAME_LENGTH: u8 = 7; | ||
| 38 | |||
| 39 | #[embassy_executor::main] | ||
| 40 | async fn main(_spawner: Spawner) { | ||
| 41 | /* | ||
| 42 | How to make this work: | ||
| 43 | |||
| 44 | - Obtain a NUCLEO-STM32WB55 from your preferred supplier. | ||
| 45 | - Download and Install STM32CubeProgrammer. | ||
| 46 | - Download stm32wb5x_FUS_fw.bin, stm32wb5x_BLE_Stack_full_fw.bin, and Release_Notes.html from | ||
| 47 | gh:STMicroelectronics/STM32CubeWB@2234d97/Projects/STM32WB_Copro_Wireless_Binaries/STM32WB5x | ||
| 48 | - Open STM32CubeProgrammer | ||
| 49 | - On the right-hand pane, click "firmware upgrade" to upgrade the st-link firmware. | ||
| 50 | - Once complete, click connect to connect to the device. | ||
| 51 | - On the left hand pane, click the RSS signal icon to open "Firmware Upgrade Services". | ||
| 52 | - In the Release_Notes.html, find the memory address that corresponds to your device for the stm32wb5x_FUS_fw.bin file | ||
| 53 | - Select that file, the memory address, "verify download", and then "Firmware Upgrade". | ||
| 54 | - Once complete, in the Release_Notes.html, find the memory address that corresponds to your device for the | ||
| 55 | stm32wb5x_BLE_Stack_full_fw.bin file. It should not be the same memory address. | ||
| 56 | - Select that file, the memory address, "verify download", and then "Firmware Upgrade". | ||
| 57 | - Select "Start Wireless Stack". | ||
| 58 | - Disconnect from the device. | ||
| 59 | - In the examples folder for stm32wb, modify the memory.x file to match your target device. | ||
| 60 | - Run this example. | ||
| 61 | |||
| 62 | Note: extended stack versions are not supported at this time. Do not attempt to install a stack with "extended" in the name. | ||
| 63 | */ | ||
| 64 | |||
| 65 | let p = embassy_stm32::init(Default::default()); | ||
| 66 | info!("Hello World!"); | ||
| 67 | |||
| 68 | let config = Config::default(); | ||
| 69 | let mut mbox = TlMbox::init(p.IPCC, Irqs, config); | ||
| 70 | |||
| 71 | let sys_event = mbox.sys_subsystem.read().await; | ||
| 72 | info!("sys event: {}", sys_event.payload()); | ||
| 73 | |||
| 74 | let _ = mbox.sys_subsystem.shci_c2_ble_init(Default::default()).await; | ||
| 75 | |||
| 76 | info!("resetting BLE..."); | ||
| 77 | mbox.ble_subsystem.reset().await; | ||
| 78 | let response = mbox.ble_subsystem.read().await; | ||
| 79 | defmt::debug!("{}", response); | ||
| 80 | |||
| 81 | info!("config public address..."); | ||
| 82 | mbox.ble_subsystem | ||
| 83 | .write_config_data(&ConfigData::public_address(get_bd_addr()).build()) | ||
| 84 | .await; | ||
| 85 | let response = mbox.ble_subsystem.read().await; | ||
| 86 | defmt::debug!("{}", response); | ||
| 87 | |||
| 88 | info!("config random address..."); | ||
| 89 | mbox.ble_subsystem | ||
| 90 | .write_config_data(&ConfigData::random_address(get_random_addr()).build()) | ||
| 91 | .await; | ||
| 92 | let response = mbox.ble_subsystem.read().await; | ||
| 93 | defmt::debug!("{}", response); | ||
| 94 | |||
| 95 | info!("config identity root..."); | ||
| 96 | mbox.ble_subsystem | ||
| 97 | .write_config_data(&ConfigData::identity_root(&get_irk()).build()) | ||
| 98 | .await; | ||
| 99 | let response = mbox.ble_subsystem.read().await; | ||
| 100 | defmt::debug!("{}", response); | ||
| 101 | |||
| 102 | info!("config encryption root..."); | ||
| 103 | mbox.ble_subsystem | ||
| 104 | .write_config_data(&ConfigData::encryption_root(&get_erk()).build()) | ||
| 105 | .await; | ||
| 106 | let response = mbox.ble_subsystem.read().await; | ||
| 107 | defmt::debug!("{}", response); | ||
| 108 | |||
| 109 | info!("config tx power level..."); | ||
| 110 | mbox.ble_subsystem.set_tx_power_level(PowerLevel::ZerodBm).await; | ||
| 111 | let response = mbox.ble_subsystem.read().await; | ||
| 112 | defmt::debug!("{}", response); | ||
| 113 | |||
| 114 | info!("GATT init..."); | ||
| 115 | mbox.ble_subsystem.init_gatt().await; | ||
| 116 | let response = mbox.ble_subsystem.read().await; | ||
| 117 | defmt::debug!("{}", response); | ||
| 118 | |||
| 119 | info!("GAP init..."); | ||
| 120 | mbox.ble_subsystem | ||
| 121 | .init_gap(Role::PERIPHERAL, false, BLE_GAP_DEVICE_NAME_LENGTH) | ||
| 122 | .await; | ||
| 123 | let response = mbox.ble_subsystem.read().await; | ||
| 124 | defmt::debug!("{}", response); | ||
| 125 | |||
| 126 | info!("set IO capabilities..."); | ||
| 127 | mbox.ble_subsystem.set_io_capability(IoCapability::DisplayConfirm).await; | ||
| 128 | let response = mbox.ble_subsystem.read().await; | ||
| 129 | defmt::debug!("{}", response); | ||
| 130 | |||
| 131 | info!("set authentication requirements..."); | ||
| 132 | mbox.ble_subsystem | ||
| 133 | .set_authentication_requirement(&AuthenticationRequirements { | ||
| 134 | bonding_required: false, | ||
| 135 | keypress_notification_support: false, | ||
| 136 | mitm_protection_required: false, | ||
| 137 | encryption_key_size_range: (8, 16), | ||
| 138 | fixed_pin: Pin::Requested, | ||
| 139 | identity_address_type: AddressType::Public, | ||
| 140 | secure_connection_support: SecureConnectionSupport::Optional, | ||
| 141 | }) | ||
| 142 | .await | ||
| 143 | .unwrap(); | ||
| 144 | let response = mbox.ble_subsystem.read().await; | ||
| 145 | defmt::debug!("{}", response); | ||
| 146 | |||
| 147 | info!("set scan response data..."); | ||
| 148 | mbox.ble_subsystem.le_set_scan_response_data(b"TXTX").await.unwrap(); | ||
| 149 | let response = mbox.ble_subsystem.read().await; | ||
| 150 | defmt::debug!("{}", response); | ||
| 151 | |||
| 152 | info!("set scan response data..."); | ||
| 153 | mbox.ble_subsystem.le_set_scan_response_data(b"TXTX").await.unwrap(); | ||
| 154 | let response = mbox.ble_subsystem.read().await; | ||
| 155 | defmt::debug!("{}", response); | ||
| 156 | |||
| 157 | defmt::info!("initializing services and characteristics..."); | ||
| 158 | let mut ble_context = init_gatt_services(&mut mbox.ble_subsystem).await.unwrap(); | ||
| 159 | defmt::info!("{}", ble_context); | ||
| 160 | |||
| 161 | let discovery_params = DiscoverableParameters { | ||
| 162 | advertising_type: AdvertisingType::ConnectableUndirected, | ||
| 163 | advertising_interval: Some((Duration::from_millis(100), Duration::from_millis(100))), | ||
| 164 | address_type: OwnAddressType::Public, | ||
| 165 | filter_policy: AdvertisingFilterPolicy::AllowConnectionAndScan, | ||
| 166 | local_name: Some(LocalName::Complete(b"TXTX")), | ||
| 167 | advertising_data: &[], | ||
| 168 | conn_interval: (None, None), | ||
| 169 | }; | ||
| 170 | |||
| 171 | info!("set discoverable..."); | ||
| 172 | mbox.ble_subsystem.set_discoverable(&discovery_params).await.unwrap(); | ||
| 173 | let response = mbox.ble_subsystem.read().await; | ||
| 174 | defmt::debug!("{}", response); | ||
| 175 | |||
| 176 | loop { | ||
| 177 | let response = mbox.ble_subsystem.read().await; | ||
| 178 | defmt::debug!("{}", response); | ||
| 179 | |||
| 180 | if let Ok(Packet::Event(event)) = response { | ||
| 181 | match event { | ||
| 182 | Event::LeConnectionComplete(_) => { | ||
| 183 | defmt::info!("connected"); | ||
| 184 | } | ||
| 185 | Event::DisconnectionComplete(_) => { | ||
| 186 | defmt::info!("disconnected"); | ||
| 187 | ble_context.is_subscribed = false; | ||
| 188 | mbox.ble_subsystem.set_discoverable(&discovery_params).await.unwrap(); | ||
| 189 | } | ||
| 190 | Event::Vendor(vendor_event) => match vendor_event { | ||
| 191 | Stm32Wb5xEvent::AttReadPermitRequest(read_req) => { | ||
| 192 | defmt::info!("read request received {}, allowing", read_req); | ||
| 193 | mbox.ble_subsystem.allow_read(read_req.conn_handle).await | ||
| 194 | } | ||
| 195 | Stm32Wb5xEvent::AttWritePermitRequest(write_req) => { | ||
| 196 | defmt::info!("write request received {}, allowing", write_req); | ||
| 197 | mbox.ble_subsystem | ||
| 198 | .write_response(&WriteResponseParameters { | ||
| 199 | conn_handle: write_req.conn_handle, | ||
| 200 | attribute_handle: write_req.attribute_handle, | ||
| 201 | status: Ok(()), | ||
| 202 | value: write_req.value(), | ||
| 203 | }) | ||
| 204 | .await | ||
| 205 | .unwrap() | ||
| 206 | } | ||
| 207 | Stm32Wb5xEvent::GattAttributeModified(attribute) => { | ||
| 208 | defmt::info!("{}", ble_context); | ||
| 209 | if attribute.attr_handle.0 == ble_context.chars.notify.0 + 2 { | ||
| 210 | if attribute.data()[0] == 0x01 { | ||
| 211 | defmt::info!("subscribed"); | ||
| 212 | ble_context.is_subscribed = true; | ||
| 213 | } else { | ||
| 214 | defmt::info!("unsubscribed"); | ||
| 215 | ble_context.is_subscribed = false; | ||
| 216 | } | ||
| 217 | } | ||
| 218 | } | ||
| 219 | _ => {} | ||
| 220 | }, | ||
| 221 | _ => {} | ||
| 222 | } | ||
| 223 | } | ||
| 224 | } | ||
| 225 | } | ||
| 226 | |||
| 227 | fn get_bd_addr() -> BdAddr { | ||
| 228 | let mut bytes = [0u8; 6]; | ||
| 229 | |||
| 230 | let lhci_info = LhciC1DeviceInformationCcrp::new(); | ||
| 231 | bytes[0] = (lhci_info.uid64 & 0xff) as u8; | ||
| 232 | bytes[1] = ((lhci_info.uid64 >> 8) & 0xff) as u8; | ||
| 233 | bytes[2] = ((lhci_info.uid64 >> 16) & 0xff) as u8; | ||
| 234 | bytes[3] = lhci_info.device_type_id; | ||
| 235 | bytes[4] = (lhci_info.st_company_id & 0xff) as u8; | ||
| 236 | bytes[5] = (lhci_info.st_company_id >> 8 & 0xff) as u8; | ||
| 237 | |||
| 238 | BdAddr(bytes) | ||
| 239 | } | ||
| 240 | |||
| 241 | fn get_random_addr() -> BdAddr { | ||
| 242 | let mut bytes = [0u8; 6]; | ||
| 243 | |||
| 244 | let lhci_info = LhciC1DeviceInformationCcrp::new(); | ||
| 245 | bytes[0] = (lhci_info.uid64 & 0xff) as u8; | ||
| 246 | bytes[1] = ((lhci_info.uid64 >> 8) & 0xff) as u8; | ||
| 247 | bytes[2] = ((lhci_info.uid64 >> 16) & 0xff) as u8; | ||
| 248 | bytes[3] = 0; | ||
| 249 | bytes[4] = 0x6E; | ||
| 250 | bytes[5] = 0xED; | ||
| 251 | |||
| 252 | BdAddr(bytes) | ||
| 253 | } | ||
| 254 | |||
| 255 | const BLE_CFG_IRK: [u8; 16] = [ | ||
| 256 | 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, | ||
| 257 | ]; | ||
| 258 | const BLE_CFG_ERK: [u8; 16] = [ | ||
| 259 | 0xfe, 0xdc, 0xba, 0x09, 0x87, 0x65, 0x43, 0x21, 0xfe, 0xdc, 0xba, 0x09, 0x87, 0x65, 0x43, 0x21, | ||
| 260 | ]; | ||
| 261 | |||
| 262 | fn get_irk() -> EncryptionKey { | ||
| 263 | EncryptionKey(BLE_CFG_IRK) | ||
| 264 | } | ||
| 265 | |||
| 266 | fn get_erk() -> EncryptionKey { | ||
| 267 | EncryptionKey(BLE_CFG_ERK) | ||
| 268 | } | ||
| 269 | |||
| 270 | #[derive(defmt::Format)] | ||
| 271 | pub struct BleContext { | ||
| 272 | pub service_handle: AttributeHandle, | ||
| 273 | pub chars: CharHandles, | ||
| 274 | pub is_subscribed: bool, | ||
| 275 | } | ||
| 276 | |||
| 277 | #[derive(defmt::Format)] | ||
| 278 | pub struct CharHandles { | ||
| 279 | pub read: AttributeHandle, | ||
| 280 | pub write: AttributeHandle, | ||
| 281 | pub notify: AttributeHandle, | ||
| 282 | } | ||
| 283 | |||
| 284 | pub async fn init_gatt_services(ble_subsystem: &mut Ble) -> Result<BleContext, ()> { | ||
| 285 | let service_handle = gatt_add_service(ble_subsystem, Uuid::Uuid16(0x500)).await?; | ||
| 286 | |||
| 287 | let read = gatt_add_char( | ||
| 288 | ble_subsystem, | ||
| 289 | service_handle, | ||
| 290 | Uuid::Uuid16(0x501), | ||
| 291 | CharacteristicProperty::READ, | ||
| 292 | Some(b"Hello from embassy!"), | ||
| 293 | ) | ||
| 294 | .await?; | ||
| 295 | |||
| 296 | let write = gatt_add_char( | ||
| 297 | ble_subsystem, | ||
| 298 | service_handle, | ||
| 299 | Uuid::Uuid16(0x502), | ||
| 300 | CharacteristicProperty::WRITE_WITHOUT_RESPONSE | CharacteristicProperty::WRITE | CharacteristicProperty::READ, | ||
| 301 | None, | ||
| 302 | ) | ||
| 303 | .await?; | ||
| 304 | |||
| 305 | let notify = gatt_add_char( | ||
| 306 | ble_subsystem, | ||
| 307 | service_handle, | ||
| 308 | Uuid::Uuid16(0x503), | ||
| 309 | CharacteristicProperty::NOTIFY | CharacteristicProperty::READ, | ||
| 310 | None, | ||
| 311 | ) | ||
| 312 | .await?; | ||
| 313 | |||
| 314 | Ok(BleContext { | ||
| 315 | service_handle, | ||
| 316 | is_subscribed: false, | ||
| 317 | chars: CharHandles { read, write, notify }, | ||
| 318 | }) | ||
| 319 | } | ||
| 320 | |||
| 321 | async fn gatt_add_service(ble_subsystem: &mut Ble, uuid: Uuid) -> Result<AttributeHandle, ()> { | ||
| 322 | ble_subsystem | ||
| 323 | .add_service(&AddServiceParameters { | ||
| 324 | uuid, | ||
| 325 | service_type: ServiceType::Primary, | ||
| 326 | max_attribute_records: 8, | ||
| 327 | }) | ||
| 328 | .await; | ||
| 329 | let response = ble_subsystem.read().await; | ||
| 330 | defmt::debug!("{}", response); | ||
| 331 | |||
| 332 | if let Ok(Packet::Event(Event::CommandComplete(CommandComplete { | ||
| 333 | return_params: | ||
| 334 | ReturnParameters::Vendor(event::command::ReturnParameters::GattAddService(event::command::GattService { | ||
| 335 | service_handle, | ||
| 336 | .. | ||
| 337 | })), | ||
| 338 | .. | ||
| 339 | }))) = response | ||
| 340 | { | ||
| 341 | Ok(service_handle) | ||
| 342 | } else { | ||
| 343 | Err(()) | ||
| 344 | } | ||
| 345 | } | ||
| 346 | |||
| 347 | async fn gatt_add_char( | ||
| 348 | ble_subsystem: &mut Ble, | ||
| 349 | service_handle: AttributeHandle, | ||
| 350 | characteristic_uuid: Uuid, | ||
| 351 | characteristic_properties: CharacteristicProperty, | ||
| 352 | default_value: Option<&[u8]>, | ||
| 353 | ) -> Result<AttributeHandle, ()> { | ||
| 354 | ble_subsystem | ||
| 355 | .add_characteristic(&AddCharacteristicParameters { | ||
| 356 | service_handle, | ||
| 357 | characteristic_uuid, | ||
| 358 | characteristic_properties, | ||
| 359 | characteristic_value_len: 32, | ||
| 360 | security_permissions: CharacteristicPermission::empty(), | ||
| 361 | gatt_event_mask: CharacteristicEvent::all(), | ||
| 362 | encryption_key_size: EncryptionKeySize::with_value(7).unwrap(), | ||
| 363 | is_variable: true, | ||
| 364 | }) | ||
| 365 | .await; | ||
| 366 | let response = ble_subsystem.read().await; | ||
| 367 | defmt::debug!("{}", response); | ||
| 368 | |||
| 369 | if let Ok(Packet::Event(Event::CommandComplete(CommandComplete { | ||
| 370 | return_params: | ||
| 371 | ReturnParameters::Vendor(event::command::ReturnParameters::GattAddCharacteristic( | ||
| 372 | event::command::GattCharacteristic { | ||
| 373 | characteristic_handle, .. | ||
| 374 | }, | ||
| 375 | )), | ||
| 376 | .. | ||
| 377 | }))) = response | ||
| 378 | { | ||
| 379 | if let Some(value) = default_value { | ||
| 380 | ble_subsystem | ||
| 381 | .update_characteristic_value(&UpdateCharacteristicValueParameters { | ||
| 382 | service_handle, | ||
| 383 | characteristic_handle, | ||
| 384 | offset: 0, | ||
| 385 | value, | ||
| 386 | }) | ||
| 387 | .await | ||
| 388 | .unwrap(); | ||
| 389 | |||
| 390 | let response = ble_subsystem.read().await; | ||
| 391 | defmt::debug!("{}", response); | ||
| 392 | } | ||
| 393 | Ok(characteristic_handle) | ||
| 394 | } else { | ||
| 395 | Err(()) | ||
| 396 | } | ||
| 397 | } | ||
diff --git a/examples/stm32wb/src/bin/mac_ffd.rs b/examples/stm32wb/src/bin/mac_ffd.rs new file mode 100644 index 000000000..e4d81997e --- /dev/null +++ b/examples/stm32wb/src/bin/mac_ffd.rs | |||
| @@ -0,0 +1,183 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | #![feature(type_alias_impl_trait)] | ||
| 4 | |||
| 5 | use defmt::*; | ||
| 6 | use embassy_executor::Spawner; | ||
| 7 | use embassy_stm32::bind_interrupts; | ||
| 8 | use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler}; | ||
| 9 | use embassy_stm32_wpan::mac::commands::{AssociateResponse, ResetRequest, SetRequest, StartRequest}; | ||
| 10 | use embassy_stm32_wpan::mac::event::MacEvent; | ||
| 11 | use embassy_stm32_wpan::mac::typedefs::{MacChannel, MacStatus, PanId, PibId, SecurityLevel}; | ||
| 12 | use embassy_stm32_wpan::sub::mm; | ||
| 13 | use embassy_stm32_wpan::TlMbox; | ||
| 14 | use {defmt_rtt as _, panic_probe as _}; | ||
| 15 | |||
| 16 | bind_interrupts!(struct Irqs{ | ||
| 17 | IPCC_C1_RX => ReceiveInterruptHandler; | ||
| 18 | IPCC_C1_TX => TransmitInterruptHandler; | ||
| 19 | }); | ||
| 20 | |||
| 21 | #[embassy_executor::task] | ||
| 22 | async fn run_mm_queue(memory_manager: mm::MemoryManager) { | ||
| 23 | memory_manager.run_queue().await; | ||
| 24 | } | ||
| 25 | |||
| 26 | #[embassy_executor::main] | ||
| 27 | async fn main(spawner: Spawner) { | ||
| 28 | /* | ||
| 29 | How to make this work: | ||
| 30 | |||
| 31 | - Obtain a NUCLEO-STM32WB55 from your preferred supplier. | ||
| 32 | - Download and Install STM32CubeProgrammer. | ||
| 33 | - Download stm32wb5x_FUS_fw.bin, stm32wb5x_BLE_Stack_full_fw.bin, and Release_Notes.html from | ||
| 34 | gh:STMicroelectronics/STM32CubeWB@2234d97/Projects/STM32WB_Copro_Wireless_Binaries/STM32WB5x | ||
| 35 | - Open STM32CubeProgrammer | ||
| 36 | - On the right-hand pane, click "firmware upgrade" to upgrade the st-link firmware. | ||
| 37 | - Once complete, click connect to connect to the device. | ||
| 38 | - On the left hand pane, click the RSS signal icon to open "Firmware Upgrade Services". | ||
| 39 | - In the Release_Notes.html, find the memory address that corresponds to your device for the stm32wb5x_FUS_fw.bin file | ||
| 40 | - Select that file, the memory address, "verify download", and then "Firmware Upgrade". | ||
| 41 | - Once complete, in the Release_Notes.html, find the memory address that corresponds to your device for the | ||
| 42 | stm32wb5x_BLE_Stack_full_fw.bin file. It should not be the same memory address. | ||
| 43 | - Select that file, the memory address, "verify download", and then "Firmware Upgrade". | ||
| 44 | - Select "Start Wireless Stack". | ||
| 45 | - Disconnect from the device. | ||
| 46 | - In the examples folder for stm32wb, modify the memory.x file to match your target device. | ||
| 47 | - Run this example. | ||
| 48 | |||
| 49 | Note: extended stack versions are not supported at this time. Do not attempt to install a stack with "extended" in the name. | ||
| 50 | */ | ||
| 51 | |||
| 52 | let p = embassy_stm32::init(Default::default()); | ||
| 53 | info!("Hello World!"); | ||
| 54 | |||
| 55 | let config = Config::default(); | ||
| 56 | let mbox = TlMbox::init(p.IPCC, Irqs, config); | ||
| 57 | |||
| 58 | spawner.spawn(run_mm_queue(mbox.mm_subsystem)).unwrap(); | ||
| 59 | |||
| 60 | let sys_event = mbox.sys_subsystem.read().await; | ||
| 61 | info!("sys event: {}", sys_event.payload()); | ||
| 62 | |||
| 63 | core::mem::drop(sys_event); | ||
| 64 | |||
| 65 | let result = mbox.sys_subsystem.shci_c2_mac_802_15_4_init().await; | ||
| 66 | info!("initialized mac: {}", result); | ||
| 67 | |||
| 68 | info!("resetting"); | ||
| 69 | mbox.mac_subsystem | ||
| 70 | .send_command(&ResetRequest { set_default_pib: true }) | ||
| 71 | .await | ||
| 72 | .unwrap(); | ||
| 73 | let evt = mbox.mac_subsystem.read().await; | ||
| 74 | defmt::info!("{:#x}", evt); | ||
| 75 | |||
| 76 | info!("setting extended address"); | ||
| 77 | let extended_address: u64 = 0xACDE480000000001; | ||
| 78 | mbox.mac_subsystem | ||
| 79 | .send_command(&SetRequest { | ||
| 80 | pib_attribute_ptr: &extended_address as *const _ as *const u8, | ||
| 81 | pib_attribute: PibId::ExtendedAddress, | ||
| 82 | }) | ||
| 83 | .await | ||
| 84 | .unwrap(); | ||
| 85 | let evt = mbox.mac_subsystem.read().await; | ||
| 86 | defmt::info!("{:#x}", evt); | ||
| 87 | |||
| 88 | info!("setting short address"); | ||
| 89 | let short_address: u16 = 0x1122; | ||
| 90 | mbox.mac_subsystem | ||
| 91 | .send_command(&SetRequest { | ||
| 92 | pib_attribute_ptr: &short_address as *const _ as *const u8, | ||
| 93 | pib_attribute: PibId::ShortAddress, | ||
| 94 | }) | ||
| 95 | .await | ||
| 96 | .unwrap(); | ||
| 97 | let evt = mbox.mac_subsystem.read().await; | ||
| 98 | defmt::info!("{:#x}", evt); | ||
| 99 | |||
| 100 | info!("setting association permit"); | ||
| 101 | let association_permit: bool = true; | ||
| 102 | mbox.mac_subsystem | ||
| 103 | .send_command(&SetRequest { | ||
| 104 | pib_attribute_ptr: &association_permit as *const _ as *const u8, | ||
| 105 | pib_attribute: PibId::AssociationPermit, | ||
| 106 | }) | ||
| 107 | .await | ||
| 108 | .unwrap(); | ||
| 109 | let evt = mbox.mac_subsystem.read().await; | ||
| 110 | defmt::info!("{:#x}", evt); | ||
| 111 | |||
| 112 | info!("setting TX power"); | ||
| 113 | let transmit_power: i8 = 2; | ||
| 114 | mbox.mac_subsystem | ||
| 115 | .send_command(&SetRequest { | ||
| 116 | pib_attribute_ptr: &transmit_power as *const _ as *const u8, | ||
| 117 | pib_attribute: PibId::TransmitPower, | ||
| 118 | }) | ||
| 119 | .await | ||
| 120 | .unwrap(); | ||
| 121 | let evt = mbox.mac_subsystem.read().await; | ||
| 122 | defmt::info!("{:#x}", evt); | ||
| 123 | |||
| 124 | info!("starting FFD device"); | ||
| 125 | mbox.mac_subsystem | ||
| 126 | .send_command(&StartRequest { | ||
| 127 | pan_id: PanId([0x1A, 0xAA]), | ||
| 128 | channel_number: MacChannel::Channel16, | ||
| 129 | beacon_order: 0x0F, | ||
| 130 | superframe_order: 0x0F, | ||
| 131 | pan_coordinator: true, | ||
| 132 | battery_life_extension: false, | ||
| 133 | ..Default::default() | ||
| 134 | }) | ||
| 135 | .await | ||
| 136 | .unwrap(); | ||
| 137 | let evt = mbox.mac_subsystem.read().await; | ||
| 138 | defmt::info!("{:#x}", evt); | ||
| 139 | |||
| 140 | info!("setting RX on when idle"); | ||
| 141 | let rx_on_while_idle: bool = true; | ||
| 142 | mbox.mac_subsystem | ||
| 143 | .send_command(&SetRequest { | ||
| 144 | pib_attribute_ptr: &rx_on_while_idle as *const _ as *const u8, | ||
| 145 | pib_attribute: PibId::RxOnWhenIdle, | ||
| 146 | }) | ||
| 147 | .await | ||
| 148 | .unwrap(); | ||
| 149 | let evt = mbox.mac_subsystem.read().await; | ||
| 150 | defmt::info!("{:#x}", evt); | ||
| 151 | |||
| 152 | loop { | ||
| 153 | let evt = mbox.mac_subsystem.read().await; | ||
| 154 | defmt::info!("{:#x}", evt); | ||
| 155 | |||
| 156 | if let Ok(evt) = evt { | ||
| 157 | match evt { | ||
| 158 | MacEvent::MlmeAssociateInd(association) => mbox | ||
| 159 | .mac_subsystem | ||
| 160 | .send_command(&AssociateResponse { | ||
| 161 | device_address: association.device_address, | ||
| 162 | assoc_short_address: [0x33, 0x44], | ||
| 163 | status: MacStatus::Success, | ||
| 164 | security_level: SecurityLevel::Unsecure, | ||
| 165 | ..Default::default() | ||
| 166 | }) | ||
| 167 | .await | ||
| 168 | .unwrap(), | ||
| 169 | MacEvent::McpsDataInd(data_ind) => { | ||
| 170 | let data_addr = data_ind.msdu_ptr; | ||
| 171 | let mut data = [0u8; 256]; | ||
| 172 | unsafe { data_addr.copy_to(&mut data as *mut _, data_ind.msdu_length as usize) } | ||
| 173 | info!("{}", data[..data_ind.msdu_length as usize]); | ||
| 174 | |||
| 175 | if &data[..data_ind.msdu_length as usize] == b"Hello from embassy!" { | ||
| 176 | info!("success"); | ||
| 177 | } | ||
| 178 | } | ||
| 179 | _ => {} | ||
| 180 | } | ||
| 181 | } | ||
| 182 | } | ||
| 183 | } | ||
diff --git a/examples/stm32wb/src/bin/mac_rfd.rs b/examples/stm32wb/src/bin/mac_rfd.rs new file mode 100644 index 000000000..b2dac72cc --- /dev/null +++ b/examples/stm32wb/src/bin/mac_rfd.rs | |||
| @@ -0,0 +1,170 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | #![feature(type_alias_impl_trait)] | ||
| 4 | |||
| 5 | use defmt::*; | ||
| 6 | use embassy_executor::Spawner; | ||
| 7 | use embassy_stm32::bind_interrupts; | ||
| 8 | use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler}; | ||
| 9 | use embassy_stm32_wpan::mac::commands::{AssociateRequest, DataRequest, GetRequest, ResetRequest, SetRequest}; | ||
| 10 | use embassy_stm32_wpan::mac::event::MacEvent; | ||
| 11 | use embassy_stm32_wpan::mac::typedefs::{ | ||
| 12 | AddressMode, Capabilities, KeyIdMode, MacAddress, MacChannel, PanId, PibId, SecurityLevel, | ||
| 13 | }; | ||
| 14 | use embassy_stm32_wpan::sub::mm; | ||
| 15 | use embassy_stm32_wpan::TlMbox; | ||
| 16 | use {defmt_rtt as _, panic_probe as _}; | ||
| 17 | |||
| 18 | bind_interrupts!(struct Irqs{ | ||
| 19 | IPCC_C1_RX => ReceiveInterruptHandler; | ||
| 20 | IPCC_C1_TX => TransmitInterruptHandler; | ||
| 21 | }); | ||
| 22 | |||
| 23 | #[embassy_executor::task] | ||
| 24 | async fn run_mm_queue(memory_manager: mm::MemoryManager) { | ||
| 25 | memory_manager.run_queue().await; | ||
| 26 | } | ||
| 27 | |||
| 28 | #[embassy_executor::main] | ||
| 29 | async fn main(spawner: Spawner) { | ||
| 30 | /* | ||
| 31 | How to make this work: | ||
| 32 | |||
| 33 | - Obtain a NUCLEO-STM32WB55 from your preferred supplier. | ||
| 34 | - Download and Install STM32CubeProgrammer. | ||
| 35 | - Download stm32wb5x_FUS_fw.bin, stm32wb5x_BLE_Stack_full_fw.bin, and Release_Notes.html from | ||
| 36 | gh:STMicroelectronics/STM32CubeWB@2234d97/Projects/STM32WB_Copro_Wireless_Binaries/STM32WB5x | ||
| 37 | - Open STM32CubeProgrammer | ||
| 38 | - On the right-hand pane, click "firmware upgrade" to upgrade the st-link firmware. | ||
| 39 | - Once complete, click connect to connect to the device. | ||
| 40 | - On the left hand pane, click the RSS signal icon to open "Firmware Upgrade Services". | ||
| 41 | - In the Release_Notes.html, find the memory address that corresponds to your device for the stm32wb5x_FUS_fw.bin file | ||
| 42 | - Select that file, the memory address, "verify download", and then "Firmware Upgrade". | ||
| 43 | - Once complete, in the Release_Notes.html, find the memory address that corresponds to your device for the | ||
| 44 | stm32wb5x_BLE_Stack_full_fw.bin file. It should not be the same memory address. | ||
| 45 | - Select that file, the memory address, "verify download", and then "Firmware Upgrade". | ||
| 46 | - Select "Start Wireless Stack". | ||
| 47 | - Disconnect from the device. | ||
| 48 | - In the examples folder for stm32wb, modify the memory.x file to match your target device. | ||
| 49 | - Run this example. | ||
| 50 | |||
| 51 | Note: extended stack versions are not supported at this time. Do not attempt to install a stack with "extended" in the name. | ||
| 52 | */ | ||
| 53 | |||
| 54 | let p = embassy_stm32::init(Default::default()); | ||
| 55 | info!("Hello World!"); | ||
| 56 | |||
| 57 | let config = Config::default(); | ||
| 58 | let mbox = TlMbox::init(p.IPCC, Irqs, config); | ||
| 59 | |||
| 60 | spawner.spawn(run_mm_queue(mbox.mm_subsystem)).unwrap(); | ||
| 61 | |||
| 62 | let sys_event = mbox.sys_subsystem.read().await; | ||
| 63 | info!("sys event: {}", sys_event.payload()); | ||
| 64 | |||
| 65 | core::mem::drop(sys_event); | ||
| 66 | |||
| 67 | let result = mbox.sys_subsystem.shci_c2_mac_802_15_4_init().await; | ||
| 68 | info!("initialized mac: {}", result); | ||
| 69 | |||
| 70 | info!("resetting"); | ||
| 71 | mbox.mac_subsystem | ||
| 72 | .send_command(&ResetRequest { set_default_pib: true }) | ||
| 73 | .await | ||
| 74 | .unwrap(); | ||
| 75 | let evt = mbox.mac_subsystem.read().await; | ||
| 76 | info!("{:#x}", evt); | ||
| 77 | |||
| 78 | info!("setting extended address"); | ||
| 79 | let extended_address: u64 = 0xACDE480000000002; | ||
| 80 | mbox.mac_subsystem | ||
| 81 | .send_command(&SetRequest { | ||
| 82 | pib_attribute_ptr: &extended_address as *const _ as *const u8, | ||
| 83 | pib_attribute: PibId::ExtendedAddress, | ||
| 84 | }) | ||
| 85 | .await | ||
| 86 | .unwrap(); | ||
| 87 | let evt = mbox.mac_subsystem.read().await; | ||
| 88 | info!("{:#x}", evt); | ||
| 89 | |||
| 90 | info!("getting extended address"); | ||
| 91 | mbox.mac_subsystem | ||
| 92 | .send_command(&GetRequest { | ||
| 93 | pib_attribute: PibId::ExtendedAddress, | ||
| 94 | }) | ||
| 95 | .await | ||
| 96 | .unwrap(); | ||
| 97 | let evt = mbox.mac_subsystem.read().await; | ||
| 98 | info!("{:#x}", evt); | ||
| 99 | |||
| 100 | if let Ok(MacEvent::MlmeGetCnf(evt)) = evt { | ||
| 101 | if evt.pib_attribute_value_len == 8 { | ||
| 102 | let value = unsafe { core::ptr::read_unaligned(evt.pib_attribute_value_ptr as *const u64) }; | ||
| 103 | |||
| 104 | info!("value {:#x}", value) | ||
| 105 | } | ||
| 106 | } | ||
| 107 | |||
| 108 | info!("assocation request"); | ||
| 109 | let a = AssociateRequest { | ||
| 110 | channel_number: MacChannel::Channel16, | ||
| 111 | channel_page: 0, | ||
| 112 | coord_addr_mode: AddressMode::Short, | ||
| 113 | coord_address: MacAddress { short: [34, 17] }, | ||
| 114 | capability_information: Capabilities::ALLOCATE_ADDRESS, | ||
| 115 | coord_pan_id: PanId([0x1A, 0xAA]), | ||
| 116 | security_level: SecurityLevel::Unsecure, | ||
| 117 | key_id_mode: KeyIdMode::Implicite, | ||
| 118 | key_source: [0; 8], | ||
| 119 | key_index: 152, | ||
| 120 | }; | ||
| 121 | info!("{}", a); | ||
| 122 | mbox.mac_subsystem.send_command(&a).await.unwrap(); | ||
| 123 | let evt = mbox.mac_subsystem.read().await; | ||
| 124 | info!("{:#x}", evt); | ||
| 125 | |||
| 126 | let short_addr = if let Ok(MacEvent::MlmeAssociateCnf(conf)) = evt { | ||
| 127 | conf.assoc_short_address | ||
| 128 | } else { | ||
| 129 | defmt::panic!() | ||
| 130 | }; | ||
| 131 | |||
| 132 | info!("setting short address"); | ||
| 133 | mbox.mac_subsystem | ||
| 134 | .send_command(&SetRequest { | ||
| 135 | pib_attribute_ptr: &short_addr as *const _ as *const u8, | ||
| 136 | pib_attribute: PibId::ShortAddress, | ||
| 137 | }) | ||
| 138 | .await | ||
| 139 | .unwrap(); | ||
| 140 | let evt = mbox.mac_subsystem.read().await; | ||
| 141 | info!("{:#x}", evt); | ||
| 142 | |||
| 143 | info!("sending data"); | ||
| 144 | let mut data_buffer = [0u8; 256]; | ||
| 145 | let data = b"Hello from embassy!"; | ||
| 146 | data_buffer[..data.len()].copy_from_slice(data); | ||
| 147 | mbox.mac_subsystem | ||
| 148 | .send_command(&DataRequest { | ||
| 149 | src_addr_mode: AddressMode::Short, | ||
| 150 | dst_addr_mode: AddressMode::Short, | ||
| 151 | dst_pan_id: PanId([0x1A, 0xAA]), | ||
| 152 | dst_address: MacAddress::BROADCAST, | ||
| 153 | msdu_handle: 0x02, | ||
| 154 | ack_tx: 0x00, | ||
| 155 | gts_tx: false, | ||
| 156 | msdu_ptr: &data_buffer as *const _ as *const u8, | ||
| 157 | msdu_length: data.len() as u8, | ||
| 158 | security_level: SecurityLevel::Unsecure, | ||
| 159 | ..Default::default() | ||
| 160 | }) | ||
| 161 | .await | ||
| 162 | .unwrap(); | ||
| 163 | let evt = mbox.mac_subsystem.read().await; | ||
| 164 | info!("{:#x}", evt); | ||
| 165 | |||
| 166 | loop { | ||
| 167 | let evt = mbox.mac_subsystem.read().await; | ||
| 168 | info!("{:#x}", evt); | ||
| 169 | } | ||
| 170 | } | ||
diff --git a/examples/stm32wb/src/bin/tl_mbox_ble.rs b/examples/stm32wb/src/bin/tl_mbox_ble.rs index a511e89aa..90349422e 100644 --- a/examples/stm32wb/src/bin/tl_mbox_ble.rs +++ b/examples/stm32wb/src/bin/tl_mbox_ble.rs | |||
| @@ -49,7 +49,7 @@ async fn main(_spawner: Spawner) { | |||
| 49 | let sys_event = mbox.sys_subsystem.read().await; | 49 | let sys_event = mbox.sys_subsystem.read().await; |
| 50 | info!("sys event: {}", sys_event.payload()); | 50 | info!("sys event: {}", sys_event.payload()); |
| 51 | 51 | ||
| 52 | mbox.sys_subsystem.shci_c2_ble_init(Default::default()).await; | 52 | let _ = mbox.sys_subsystem.shci_c2_ble_init(Default::default()).await; |
| 53 | 53 | ||
| 54 | info!("starting ble..."); | 54 | info!("starting ble..."); |
| 55 | mbox.ble_subsystem.tl_write(0x0c, &[]).await; | 55 | mbox.ble_subsystem.tl_write(0x0c, &[]).await; |
diff --git a/examples/stm32wb/src/bin/tl_mbox_mac.rs b/examples/stm32wb/src/bin/tl_mbox_mac.rs index f67be4682..5931c392b 100644 --- a/examples/stm32wb/src/bin/tl_mbox_mac.rs +++ b/examples/stm32wb/src/bin/tl_mbox_mac.rs | |||
| @@ -6,6 +6,7 @@ use defmt::*; | |||
| 6 | use embassy_executor::Spawner; | 6 | use embassy_executor::Spawner; |
| 7 | use embassy_stm32::bind_interrupts; | 7 | use embassy_stm32::bind_interrupts; |
| 8 | use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler}; | 8 | use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler}; |
| 9 | use embassy_stm32_wpan::sub::mm; | ||
| 9 | use embassy_stm32_wpan::TlMbox; | 10 | use embassy_stm32_wpan::TlMbox; |
| 10 | use {defmt_rtt as _, panic_probe as _}; | 11 | use {defmt_rtt as _, panic_probe as _}; |
| 11 | 12 | ||
| @@ -14,8 +15,13 @@ bind_interrupts!(struct Irqs{ | |||
| 14 | IPCC_C1_TX => TransmitInterruptHandler; | 15 | IPCC_C1_TX => TransmitInterruptHandler; |
| 15 | }); | 16 | }); |
| 16 | 17 | ||
| 18 | #[embassy_executor::task] | ||
| 19 | async fn run_mm_queue(memory_manager: mm::MemoryManager) { | ||
| 20 | memory_manager.run_queue().await; | ||
| 21 | } | ||
| 22 | |||
| 17 | #[embassy_executor::main] | 23 | #[embassy_executor::main] |
| 18 | async fn main(_spawner: Spawner) { | 24 | async fn main(spawner: Spawner) { |
| 19 | /* | 25 | /* |
| 20 | How to make this work: | 26 | How to make this work: |
| 21 | 27 | ||
| @@ -46,9 +52,13 @@ async fn main(_spawner: Spawner) { | |||
| 46 | let config = Config::default(); | 52 | let config = Config::default(); |
| 47 | let mbox = TlMbox::init(p.IPCC, Irqs, config); | 53 | let mbox = TlMbox::init(p.IPCC, Irqs, config); |
| 48 | 54 | ||
| 55 | spawner.spawn(run_mm_queue(mbox.mm_subsystem)).unwrap(); | ||
| 56 | |||
| 49 | let sys_event = mbox.sys_subsystem.read().await; | 57 | let sys_event = mbox.sys_subsystem.read().await; |
| 50 | info!("sys event: {}", sys_event.payload()); | 58 | info!("sys event: {}", sys_event.payload()); |
| 51 | 59 | ||
| 60 | core::mem::drop(sys_event); | ||
| 61 | |||
| 52 | let result = mbox.sys_subsystem.shci_c2_mac_802_15_4_init().await; | 62 | let result = mbox.sys_subsystem.shci_c2_mac_802_15_4_init().await; |
| 53 | info!("initialized mac: {}", result); | 63 | info!("initialized mac: {}", result); |
| 54 | 64 | ||
diff --git a/examples/stm32wl/.cargo/config.toml b/examples/stm32wl/.cargo/config.toml index 4f8094ff2..ee416fcbc 100644 --- a/examples/stm32wl/.cargo/config.toml +++ b/examples/stm32wl/.cargo/config.toml | |||
| @@ -3,7 +3,7 @@ | |||
| 3 | runner = "probe-rs run --chip STM32WLE5JCIx" | 3 | runner = "probe-rs run --chip STM32WLE5JCIx" |
| 4 | 4 | ||
| 5 | [build] | 5 | [build] |
| 6 | target = "thumbv7em-none-eabihf" | 6 | target = "thumbv7em-none-eabi" |
| 7 | 7 | ||
| 8 | [env] | 8 | [env] |
| 9 | DEFMT_LOG = "trace" | 9 | DEFMT_LOG = "trace" |
diff --git a/examples/stm32wl/Cargo.toml b/examples/stm32wl/Cargo.toml index 260f9afa1..e2c66f456 100644 --- a/examples/stm32wl/Cargo.toml +++ b/examples/stm32wl/Cargo.toml | |||
| @@ -7,9 +7,9 @@ license = "MIT OR Apache-2.0" | |||
| 7 | [dependencies] | 7 | [dependencies] |
| 8 | embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] } | 8 | embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] } |
| 9 | embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } | 9 | embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } |
| 10 | embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["nightly", "unstable-traits", "defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } | 10 | embassy-time = { version = "0.1.2", path = "../../embassy-time", features = ["nightly", "unstable-traits", "defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } |
| 11 | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "unstable-traits", "defmt", "stm32wl55jc-cm4", "time-driver-any", "memory-x", "unstable-pac", "exti"] } | 11 | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "unstable-traits", "defmt", "stm32wl55jc-cm4", "time-driver-any", "memory-x", "unstable-pac", "exti", "chrono"] } |
| 12 | embassy-embedded-hal = {version = "0.1.0", path = "../../embassy-embedded-hal" } | 12 | embassy-embedded-hal = { version = "0.1.0", path = "../../embassy-embedded-hal" } |
| 13 | embassy-lora = { version = "0.1.0", path = "../../embassy-lora", features = ["stm32wl", "time", "defmt"] } | 13 | embassy-lora = { version = "0.1.0", path = "../../embassy-lora", features = ["stm32wl", "time", "defmt"] } |
| 14 | lora-phy = { version = "1" } | 14 | lora-phy = { version = "1" } |
| 15 | lorawan-device = { version = "0.10.0", default-features = false, features = ["async", "external-lora-phy"] } | 15 | lorawan-device = { version = "0.10.0", default-features = false, features = ["async", "external-lora-phy"] } |
| @@ -25,3 +25,7 @@ embedded-storage = "0.3.0" | |||
| 25 | panic-probe = { version = "0.3", features = ["print-defmt"] } | 25 | panic-probe = { version = "0.3", features = ["print-defmt"] } |
| 26 | futures = { version = "0.3.17", default-features = false, features = ["async-await"] } | 26 | futures = { version = "0.3.17", default-features = false, features = ["async-await"] } |
| 27 | heapless = { version = "0.7.5", default-features = false } | 27 | heapless = { version = "0.7.5", default-features = false } |
| 28 | chrono = { version = "^0.4", default-features = false } | ||
| 29 | |||
| 30 | [patch.crates-io] | ||
| 31 | lora-phy = { git = "https://github.com/embassy-rs/lora-phy", rev = "ad289428fd44b02788e2fa2116445cc8f640a265" } | ||
diff --git a/examples/stm32wl/src/bin/rtc.rs b/examples/stm32wl/src/bin/rtc.rs new file mode 100644 index 000000000..e11825499 --- /dev/null +++ b/examples/stm32wl/src/bin/rtc.rs | |||
| @@ -0,0 +1,43 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | #![feature(type_alias_impl_trait)] | ||
| 4 | |||
| 5 | use chrono::{NaiveDate, NaiveDateTime}; | ||
| 6 | use defmt::*; | ||
| 7 | use embassy_executor::Spawner; | ||
| 8 | use embassy_stm32::rcc::{self, ClockSrc}; | ||
| 9 | use embassy_stm32::rtc::{Rtc, RtcConfig}; | ||
| 10 | use embassy_stm32::Config; | ||
| 11 | use embassy_time::{Duration, Timer}; | ||
| 12 | use {defmt_rtt as _, panic_probe as _}; | ||
| 13 | |||
| 14 | #[embassy_executor::main] | ||
| 15 | async fn main(_spawner: Spawner) { | ||
| 16 | let p = { | ||
| 17 | let mut config = Config::default(); | ||
| 18 | config.rcc.mux = ClockSrc::HSE32; | ||
| 19 | config.rcc.rtc_mux = rcc::RtcClockSource::LSE32; | ||
| 20 | config.rcc.enable_rtc_apb = true; | ||
| 21 | embassy_stm32::init(config) | ||
| 22 | }; | ||
| 23 | info!("Hello World!"); | ||
| 24 | |||
| 25 | let now = NaiveDate::from_ymd_opt(2020, 5, 15) | ||
| 26 | .unwrap() | ||
| 27 | .and_hms_opt(10, 30, 15) | ||
| 28 | .unwrap(); | ||
| 29 | |||
| 30 | let mut rtc = Rtc::new( | ||
| 31 | p.RTC, | ||
| 32 | RtcConfig::default().clock_config(embassy_stm32::rtc::RtcClockSource::LSE), | ||
| 33 | ); | ||
| 34 | info!("Got RTC! {:?}", now.timestamp()); | ||
| 35 | |||
| 36 | rtc.set_datetime(now.into()).expect("datetime not set"); | ||
| 37 | |||
| 38 | // In reality the delay would be much longer | ||
| 39 | Timer::after(Duration::from_millis(20000)).await; | ||
| 40 | |||
| 41 | let then: NaiveDateTime = rtc.now().unwrap().into(); | ||
| 42 | info!("Got RTC! {:?}", then.timestamp()); | ||
| 43 | } | ||
diff --git a/examples/wasm/Cargo.toml b/examples/wasm/Cargo.toml index 437e443a7..3679e3857 100644 --- a/examples/wasm/Cargo.toml +++ b/examples/wasm/Cargo.toml | |||
| @@ -10,7 +10,7 @@ crate-type = ["cdylib"] | |||
| 10 | [dependencies] | 10 | [dependencies] |
| 11 | embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["log"] } | 11 | embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["log"] } |
| 12 | embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["arch-wasm", "executor-thread", "log", "nightly", "integrated-timers"] } | 12 | embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["arch-wasm", "executor-thread", "log", "nightly", "integrated-timers"] } |
| 13 | embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["log", "wasm", "nightly"] } | 13 | embassy-time = { version = "0.1.2", path = "../../embassy-time", features = ["log", "wasm", "nightly"] } |
| 14 | 14 | ||
| 15 | wasm-logger = "0.2.0" | 15 | wasm-logger = "0.2.0" |
| 16 | wasm-bindgen = "0.2" | 16 | wasm-bindgen = "0.2" |
diff --git a/rust-toolchain.toml b/rust-toolchain.toml index fd454db26..179ed1d6a 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | # Before upgrading check that everything is available on all tier1 targets here: | 1 | # Before upgrading check that everything is available on all tier1 targets here: |
| 2 | # https://rust-lang.github.io/rustup-components-history | 2 | # https://rust-lang.github.io/rustup-components-history |
| 3 | [toolchain] | 3 | [toolchain] |
| 4 | channel = "nightly-2023-05-18" | 4 | channel = "nightly-2023-06-28" |
| 5 | components = [ "rust-src", "rustfmt", "llvm-tools-preview" ] | 5 | components = [ "rust-src", "rustfmt", "llvm-tools-preview" ] |
| 6 | targets = [ | 6 | targets = [ |
| 7 | "thumbv7em-none-eabi", | 7 | "thumbv7em-none-eabi", |
| @@ -11,4 +11,4 @@ targets = [ | |||
| 11 | "thumbv8m.main-none-eabihf", | 11 | "thumbv8m.main-none-eabihf", |
| 12 | "riscv32imac-unknown-none-elf", | 12 | "riscv32imac-unknown-none-elf", |
| 13 | "wasm32-unknown-unknown", | 13 | "wasm32-unknown-unknown", |
| 14 | ] | 14 | ] \ No newline at end of file |
diff --git a/tests/nrf/Cargo.toml b/tests/nrf/Cargo.toml index 4f9ecc47a..7ce51aa5e 100644 --- a/tests/nrf/Cargo.toml +++ b/tests/nrf/Cargo.toml | |||
| @@ -10,12 +10,12 @@ teleprobe-meta = "1" | |||
| 10 | embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } | 10 | embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } |
| 11 | embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt", "nightly"] } | 11 | embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt", "nightly"] } |
| 12 | embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt", "nightly", "integrated-timers"] } | 12 | embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt", "nightly", "integrated-timers"] } |
| 13 | embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "nightly", "defmt-timestamp-uptime"] } | 13 | embassy-time = { version = "0.1.2", path = "../../embassy-time", features = ["defmt", "nightly", "unstable-traits", "defmt-timestamp-uptime"] } |
| 14 | embassy-nrf = { version = "0.1.0", path = "../../embassy-nrf", features = ["defmt", "nightly", "unstable-traits", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac"] } | 14 | embassy-nrf = { version = "0.1.0", path = "../../embassy-nrf", features = ["defmt", "nightly", "unstable-traits", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac"] } |
| 15 | embedded-io = { version = "0.4.0", features = ["async"] } | 15 | embedded-io = { version = "0.4.0", features = ["async"] } |
| 16 | embassy-net = { version = "0.1.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", "nightly"] } | 16 | embassy-net = { version = "0.1.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", "nightly"] } |
| 17 | embassy-net-esp-hosted = { version = "0.1.0", path = "../../embassy-net-esp-hosted", features = ["defmt"] } | 17 | embassy-net-esp-hosted = { version = "0.1.0", path = "../../embassy-net-esp-hosted", features = ["defmt"] } |
| 18 | embedded-hal-async = { version = "0.2.0-alpha.1" } | 18 | embedded-hal-async = { version = "0.2.0-alpha.2" } |
| 19 | static_cell = { version = "1.1", features = [ "nightly" ] } | 19 | static_cell = { version = "1.1", features = [ "nightly" ] } |
| 20 | 20 | ||
| 21 | defmt = "0.3" | 21 | defmt = "0.3" |
diff --git a/tests/nrf/src/bin/wifi_esp_hosted_perf.rs b/tests/nrf/src/bin/wifi_esp_hosted_perf.rs index 277b985c5..398ab9d27 100644 --- a/tests/nrf/src/bin/wifi_esp_hosted_perf.rs +++ b/tests/nrf/src/bin/wifi_esp_hosted_perf.rs | |||
| @@ -14,7 +14,7 @@ use embassy_nrf::gpio::{AnyPin, Input, Level, Output, OutputDrive, Pin, Pull}; | |||
| 14 | use embassy_nrf::rng::Rng; | 14 | use embassy_nrf::rng::Rng; |
| 15 | use embassy_nrf::spim::{self, Spim}; | 15 | use embassy_nrf::spim::{self, Spim}; |
| 16 | use embassy_nrf::{bind_interrupts, peripherals}; | 16 | use embassy_nrf::{bind_interrupts, peripherals}; |
| 17 | use embassy_time::{with_timeout, Duration, Timer}; | 17 | use embassy_time::{with_timeout, Delay, Duration, Timer}; |
| 18 | use embedded_hal_async::spi::ExclusiveDevice; | 18 | use embedded_hal_async::spi::ExclusiveDevice; |
| 19 | use static_cell::make_static; | 19 | use static_cell::make_static; |
| 20 | use {defmt_rtt as _, embassy_net_esp_hosted as hosted, panic_probe as _}; | 20 | use {defmt_rtt as _, embassy_net_esp_hosted as hosted, panic_probe as _}; |
| @@ -30,7 +30,7 @@ bind_interrupts!(struct Irqs { | |||
| 30 | async fn wifi_task( | 30 | async fn wifi_task( |
| 31 | runner: hosted::Runner< | 31 | runner: hosted::Runner< |
| 32 | 'static, | 32 | 'static, |
| 33 | ExclusiveDevice<Spim<'static, peripherals::SPI3>, Output<'static, peripherals::P0_31>>, | 33 | ExclusiveDevice<Spim<'static, peripherals::SPI3>, Output<'static, peripherals::P0_31>, Delay>, |
| 34 | Input<'static, AnyPin>, | 34 | Input<'static, AnyPin>, |
| 35 | Output<'static, peripherals::P1_05>, | 35 | Output<'static, peripherals::P1_05>, |
| 36 | >, | 36 | >, |
| @@ -63,7 +63,7 @@ async fn main(spawner: Spawner) { | |||
| 63 | config.frequency = spim::Frequency::M32; | 63 | config.frequency = spim::Frequency::M32; |
| 64 | config.mode = spim::MODE_2; // !!! | 64 | config.mode = spim::MODE_2; // !!! |
| 65 | let spi = spim::Spim::new(p.SPI3, Irqs, sck, miso, mosi, config); | 65 | let spi = spim::Spim::new(p.SPI3, Irqs, sck, miso, mosi, config); |
| 66 | let spi = ExclusiveDevice::new(spi, cs); | 66 | let spi = ExclusiveDevice::new(spi, cs, Delay); |
| 67 | 67 | ||
| 68 | let (device, mut control, runner) = embassy_net_esp_hosted::new( | 68 | let (device, mut control, runner) = embassy_net_esp_hosted::new( |
| 69 | make_static!(embassy_net_esp_hosted::State::new()), | 69 | make_static!(embassy_net_esp_hosted::State::new()), |
diff --git a/tests/riscv32/Cargo.toml b/tests/riscv32/Cargo.toml index 81bfdfab6..61f886c0c 100644 --- a/tests/riscv32/Cargo.toml +++ b/tests/riscv32/Cargo.toml | |||
| @@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0" | |||
| 8 | critical-section = { version = "1.1.1", features = ["restore-state-bool"] } | 8 | critical-section = { version = "1.1.1", features = ["restore-state-bool"] } |
| 9 | embassy-sync = { version = "0.2.0", path = "../../embassy-sync" } | 9 | embassy-sync = { version = "0.2.0", path = "../../embassy-sync" } |
| 10 | embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["arch-riscv32", "nightly", "executor-thread"] } | 10 | embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["arch-riscv32", "nightly", "executor-thread"] } |
| 11 | embassy-time = { version = "0.1.0", path = "../../embassy-time" } | 11 | embassy-time = { version = "0.1.2", path = "../../embassy-time" } |
| 12 | embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } | 12 | embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } |
| 13 | 13 | ||
| 14 | riscv-rt = "0.11" | 14 | riscv-rt = "0.11" |
diff --git a/tests/rp/Cargo.toml b/tests/rp/Cargo.toml index 180d0ebbe..f2c902787 100644 --- a/tests/rp/Cargo.toml +++ b/tests/rp/Cargo.toml | |||
| @@ -9,7 +9,7 @@ teleprobe-meta = "1.1" | |||
| 9 | 9 | ||
| 10 | embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] } | 10 | embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] } |
| 11 | embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } | 11 | embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } |
| 12 | embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt"] } | 12 | embassy-time = { version = "0.1.2", path = "../../embassy-time", features = ["defmt"] } |
| 13 | embassy-rp = { version = "0.1.0", path = "../../embassy-rp", features = ["nightly", "defmt", "unstable-pac", "unstable-traits", "time-driver", "critical-section-impl", "intrinsics", "rom-v2-intrinsics", "run-from-ram"] } | 13 | embassy-rp = { version = "0.1.0", path = "../../embassy-rp", features = ["nightly", "defmt", "unstable-pac", "unstable-traits", "time-driver", "critical-section-impl", "intrinsics", "rom-v2-intrinsics", "run-from-ram"] } |
| 14 | embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } | 14 | embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } |
| 15 | embassy-net = { version = "0.1.0", path = "../../embassy-net", features = ["defmt", "nightly", "tcp", "udp", "dhcpv4", "medium-ethernet"] } | 15 | embassy-net = { version = "0.1.0", path = "../../embassy-net", features = ["defmt", "nightly", "tcp", "udp", "dhcpv4", "medium-ethernet"] } |
| @@ -22,13 +22,15 @@ defmt-rtt = "0.4" | |||
| 22 | cortex-m = { version = "0.7.6" } | 22 | cortex-m = { version = "0.7.6" } |
| 23 | cortex-m-rt = "0.7.0" | 23 | cortex-m-rt = "0.7.0" |
| 24 | embedded-hal = "0.2.6" | 24 | embedded-hal = "0.2.6" |
| 25 | embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-alpha.10" } | 25 | embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-alpha.11" } |
| 26 | embedded-hal-async = { version = "=0.2.0-alpha.1" } | 26 | embedded-hal-async = { version = "=0.2.0-alpha.2" } |
| 27 | panic-probe = { version = "0.3.0", features = ["print-defmt"] } | 27 | panic-probe = { version = "0.3.0", features = ["print-defmt"] } |
| 28 | futures = { version = "0.3.17", default-features = false, features = ["async-await"] } | 28 | futures = { version = "0.3.17", default-features = false, features = ["async-await"] } |
| 29 | embedded-io = { version = "0.4.0", features = ["async"] } | 29 | embedded-io = { version = "0.4.0", features = ["async"] } |
| 30 | embedded-storage = { version = "0.3" } | 30 | embedded-storage = { version = "0.3" } |
| 31 | static_cell = { version = "1.1", features = ["nightly"]} | 31 | static_cell = { version = "1.1", features = ["nightly"]} |
| 32 | pio = "0.2" | ||
| 33 | pio-proc = "0.2" | ||
| 32 | 34 | ||
| 33 | [profile.dev] | 35 | [profile.dev] |
| 34 | debug = 2 | 36 | debug = 2 |
diff --git a/tests/rp/src/bin/adc.rs b/tests/rp/src/bin/adc.rs new file mode 100644 index 000000000..e659844ae --- /dev/null +++ b/tests/rp/src/bin/adc.rs | |||
| @@ -0,0 +1,86 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | #![feature(type_alias_impl_trait)] | ||
| 4 | #[path = "../common.rs"] | ||
| 5 | mod common; | ||
| 6 | |||
| 7 | use defmt::*; | ||
| 8 | use embassy_executor::Spawner; | ||
| 9 | use embassy_rp::adc::{Adc, Config, InterruptHandler, Pin}; | ||
| 10 | use embassy_rp::bind_interrupts; | ||
| 11 | use embassy_rp::gpio::Pull; | ||
| 12 | use {defmt_rtt as _, panic_probe as _}; | ||
| 13 | |||
| 14 | bind_interrupts!(struct Irqs { | ||
| 15 | ADC_IRQ_FIFO => InterruptHandler; | ||
| 16 | }); | ||
| 17 | |||
| 18 | #[embassy_executor::main] | ||
| 19 | async fn main(_spawner: Spawner) { | ||
| 20 | let mut p = embassy_rp::init(Default::default()); | ||
| 21 | let mut adc = Adc::new(p.ADC, Irqs, Config::default()); | ||
| 22 | |||
| 23 | { | ||
| 24 | { | ||
| 25 | let mut p = Pin::new(&mut p.PIN_26, Pull::Down); | ||
| 26 | defmt::assert!(adc.blocking_read(&mut p).unwrap() < 0b01_0000_0000); | ||
| 27 | defmt::assert!(adc.read(&mut p).await.unwrap() < 0b01_0000_0000); | ||
| 28 | } | ||
| 29 | { | ||
| 30 | let mut p = Pin::new(&mut p.PIN_26, Pull::Up); | ||
| 31 | defmt::assert!(adc.blocking_read(&mut p).unwrap() > 0b11_0000_0000); | ||
| 32 | defmt::assert!(adc.read(&mut p).await.unwrap() > 0b11_0000_0000); | ||
| 33 | } | ||
| 34 | } | ||
| 35 | // not bothering with async reads from now on | ||
| 36 | { | ||
| 37 | { | ||
| 38 | let mut p = Pin::new(&mut p.PIN_27, Pull::Down); | ||
| 39 | defmt::assert!(adc.blocking_read(&mut p).unwrap() < 0b01_0000_0000); | ||
| 40 | } | ||
| 41 | { | ||
| 42 | let mut p = Pin::new(&mut p.PIN_27, Pull::Up); | ||
| 43 | defmt::assert!(adc.blocking_read(&mut p).unwrap() > 0b11_0000_0000); | ||
| 44 | } | ||
| 45 | } | ||
| 46 | { | ||
| 47 | { | ||
| 48 | let mut p = Pin::new(&mut p.PIN_28, Pull::Down); | ||
| 49 | defmt::assert!(adc.blocking_read(&mut p).unwrap() < 0b01_0000_0000); | ||
| 50 | } | ||
| 51 | { | ||
| 52 | let mut p = Pin::new(&mut p.PIN_28, Pull::Up); | ||
| 53 | defmt::assert!(adc.blocking_read(&mut p).unwrap() > 0b11_0000_0000); | ||
| 54 | } | ||
| 55 | } | ||
| 56 | { | ||
| 57 | // gp29 is connected to vsys through a 200k/100k divider, | ||
| 58 | // adding pulls should change the value | ||
| 59 | let low = { | ||
| 60 | let mut p = Pin::new(&mut p.PIN_29, Pull::Down); | ||
| 61 | adc.blocking_read(&mut p).unwrap() | ||
| 62 | }; | ||
| 63 | let none = { | ||
| 64 | let mut p = Pin::new(&mut p.PIN_29, Pull::None); | ||
| 65 | adc.blocking_read(&mut p).unwrap() | ||
| 66 | }; | ||
| 67 | let up = { | ||
| 68 | let mut p = Pin::new(&mut p.PIN_29, Pull::Up); | ||
| 69 | adc.blocking_read(&mut p).unwrap() | ||
| 70 | }; | ||
| 71 | defmt::assert!(low < none); | ||
| 72 | defmt::assert!(none < up); | ||
| 73 | } | ||
| 74 | |||
| 75 | let temp = convert_to_celsius(adc.read_temperature().await.unwrap()); | ||
| 76 | defmt::assert!(temp > 0.0); | ||
| 77 | defmt::assert!(temp < 60.0); | ||
| 78 | |||
| 79 | info!("Test OK"); | ||
| 80 | cortex_m::asm::bkpt(); | ||
| 81 | } | ||
| 82 | |||
| 83 | fn convert_to_celsius(raw_temp: u16) -> f32 { | ||
| 84 | // According to chapter 4.9.5. Temperature Sensor in RP2040 datasheet | ||
| 85 | 27.0 - (raw_temp as f32 * 3.3 / 4096.0 - 0.706) / 0.001721 as f32 | ||
| 86 | } | ||
diff --git a/tests/rp/src/bin/cyw43-perf.rs b/tests/rp/src/bin/cyw43-perf.rs index 1ecaab266..bc127e2e5 100644 --- a/tests/rp/src/bin/cyw43-perf.rs +++ b/tests/rp/src/bin/cyw43-perf.rs | |||
| @@ -12,12 +12,16 @@ use embassy_net::tcp::TcpSocket; | |||
| 12 | use embassy_net::{Config, Ipv4Address, Stack, StackResources}; | 12 | use embassy_net::{Config, Ipv4Address, Stack, StackResources}; |
| 13 | use embassy_rp::gpio::{Level, Output}; | 13 | use embassy_rp::gpio::{Level, Output}; |
| 14 | use embassy_rp::peripherals::{DMA_CH0, PIN_23, PIN_25, PIO0}; | 14 | use embassy_rp::peripherals::{DMA_CH0, PIN_23, PIN_25, PIO0}; |
| 15 | use embassy_rp::pio::Pio; | 15 | use embassy_rp::pio::{InterruptHandler, Pio}; |
| 16 | use embassy_rp::rom_data; | 16 | use embassy_rp::{bind_interrupts, rom_data}; |
| 17 | use embassy_time::{with_timeout, Duration, Timer}; | 17 | use embassy_time::{with_timeout, Duration, Timer}; |
| 18 | use static_cell::make_static; | 18 | use static_cell::make_static; |
| 19 | use {defmt_rtt as _, panic_probe as _}; | 19 | use {defmt_rtt as _, panic_probe as _}; |
| 20 | 20 | ||
| 21 | bind_interrupts!(struct Irqs { | ||
| 22 | PIO0_IRQ_0 => InterruptHandler<PIO0>; | ||
| 23 | }); | ||
| 24 | |||
| 21 | teleprobe_meta::timeout!(120); | 25 | teleprobe_meta::timeout!(120); |
| 22 | 26 | ||
| 23 | #[embassy_executor::task] | 27 | #[embassy_executor::task] |
| @@ -51,7 +55,7 @@ async fn main(spawner: Spawner) { | |||
| 51 | 55 | ||
| 52 | let pwr = Output::new(p.PIN_23, Level::Low); | 56 | let pwr = Output::new(p.PIN_23, Level::Low); |
| 53 | let cs = Output::new(p.PIN_25, Level::High); | 57 | let cs = Output::new(p.PIN_25, Level::High); |
| 54 | let mut pio = Pio::new(p.PIO0); | 58 | let mut pio = Pio::new(p.PIO0, Irqs); |
| 55 | let spi = PioSpi::new(&mut pio.common, pio.sm0, pio.irq0, cs, p.PIN_24, p.PIN_29, p.DMA_CH0); | 59 | let spi = PioSpi::new(&mut pio.common, pio.sm0, pio.irq0, cs, p.PIN_24, p.PIN_29, p.DMA_CH0); |
| 56 | 60 | ||
| 57 | let state = make_static!(cyw43::State::new()); | 61 | let state = make_static!(cyw43::State::new()); |
diff --git a/tests/rp/src/bin/gpio.rs b/tests/rp/src/bin/gpio.rs index 51112d319..946b7dc88 100644 --- a/tests/rp/src/bin/gpio.rs +++ b/tests/rp/src/bin/gpio.rs | |||
| @@ -21,14 +21,46 @@ async fn main(_spawner: Spawner) { | |||
| 21 | let b = Input::new(&mut b, Pull::None); | 21 | let b = Input::new(&mut b, Pull::None); |
| 22 | 22 | ||
| 23 | { | 23 | { |
| 24 | let _a = Output::new(&mut a, Level::Low); | 24 | let a = Output::new(&mut a, Level::Low); |
| 25 | delay(); | 25 | delay(); |
| 26 | assert!(b.is_low()); | 26 | assert!(b.is_low()); |
| 27 | assert!(!b.is_high()); | ||
| 28 | assert!(a.is_set_low()); | ||
| 29 | assert!(!a.is_set_high()); | ||
| 27 | } | 30 | } |
| 28 | { | 31 | { |
| 29 | let _a = Output::new(&mut a, Level::High); | 32 | let mut a = Output::new(&mut a, Level::High); |
| 30 | delay(); | 33 | delay(); |
| 34 | assert!(!b.is_low()); | ||
| 31 | assert!(b.is_high()); | 35 | assert!(b.is_high()); |
| 36 | assert!(!a.is_set_low()); | ||
| 37 | assert!(a.is_set_high()); | ||
| 38 | |||
| 39 | // Test is_set_low / is_set_high | ||
| 40 | a.set_low(); | ||
| 41 | delay(); | ||
| 42 | assert!(b.is_low()); | ||
| 43 | assert!(a.is_set_low()); | ||
| 44 | assert!(!a.is_set_high()); | ||
| 45 | |||
| 46 | a.set_high(); | ||
| 47 | delay(); | ||
| 48 | assert!(b.is_high()); | ||
| 49 | assert!(!a.is_set_low()); | ||
| 50 | assert!(a.is_set_high()); | ||
| 51 | |||
| 52 | // Test toggle | ||
| 53 | a.toggle(); | ||
| 54 | delay(); | ||
| 55 | assert!(b.is_low()); | ||
| 56 | assert!(a.is_set_low()); | ||
| 57 | assert!(!a.is_set_high()); | ||
| 58 | |||
| 59 | a.toggle(); | ||
| 60 | delay(); | ||
| 61 | assert!(b.is_high()); | ||
| 62 | assert!(!a.is_set_low()); | ||
| 63 | assert!(a.is_set_high()); | ||
| 32 | } | 64 | } |
| 33 | } | 65 | } |
| 34 | 66 | ||
diff --git a/tests/rp/src/bin/pio_irq.rs b/tests/rp/src/bin/pio_irq.rs new file mode 100644 index 000000000..45004424a --- /dev/null +++ b/tests/rp/src/bin/pio_irq.rs | |||
| @@ -0,0 +1,55 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | #![feature(type_alias_impl_trait)] | ||
| 4 | #[path = "../common.rs"] | ||
| 5 | mod common; | ||
| 6 | |||
| 7 | use defmt::info; | ||
| 8 | use embassy_executor::Spawner; | ||
| 9 | use embassy_rp::bind_interrupts; | ||
| 10 | use embassy_rp::peripherals::PIO0; | ||
| 11 | use embassy_rp::pio::{Config, InterruptHandler, Pio}; | ||
| 12 | use embassy_rp::relocate::RelocatedProgram; | ||
| 13 | use {defmt_rtt as _, panic_probe as _}; | ||
| 14 | |||
| 15 | bind_interrupts!(struct Irqs { | ||
| 16 | PIO0_IRQ_0 => InterruptHandler<PIO0>; | ||
| 17 | }); | ||
| 18 | |||
| 19 | #[embassy_executor::main] | ||
| 20 | async fn main(_spawner: Spawner) { | ||
| 21 | let p = embassy_rp::init(Default::default()); | ||
| 22 | let pio = p.PIO0; | ||
| 23 | let Pio { | ||
| 24 | mut common, | ||
| 25 | sm0: mut sm, | ||
| 26 | irq_flags, | ||
| 27 | .. | ||
| 28 | } = Pio::new(pio, Irqs); | ||
| 29 | |||
| 30 | let prg = pio_proc::pio_asm!( | ||
| 31 | "irq set 0", | ||
| 32 | "irq wait 0", | ||
| 33 | "irq set 1", | ||
| 34 | // pause execution here | ||
| 35 | "irq wait 1", | ||
| 36 | ); | ||
| 37 | |||
| 38 | let relocated = RelocatedProgram::new(&prg.program); | ||
| 39 | let mut cfg = Config::default(); | ||
| 40 | cfg.use_program(&common.load_program(&relocated), &[]); | ||
| 41 | sm.set_config(&cfg); | ||
| 42 | sm.set_enable(true); | ||
| 43 | |||
| 44 | // not using the wait futures on purpose because they clear the irq bits, | ||
| 45 | // and we want to see in which order they are set. | ||
| 46 | while !irq_flags.check(0) {} | ||
| 47 | cortex_m::asm::nop(); | ||
| 48 | assert!(!irq_flags.check(1)); | ||
| 49 | irq_flags.clear(0); | ||
| 50 | cortex_m::asm::nop(); | ||
| 51 | assert!(irq_flags.check(1)); | ||
| 52 | |||
| 53 | info!("Test OK"); | ||
| 54 | cortex_m::asm::bkpt(); | ||
| 55 | } | ||
diff --git a/tests/stm32/Cargo.toml b/tests/stm32/Cargo.toml index c2422f7bc..3007cd1e6 100644 --- a/tests/stm32/Cargo.toml +++ b/tests/stm32/Cargo.toml | |||
| @@ -12,14 +12,16 @@ stm32g071rb = ["embassy-stm32/stm32g071rb", "not-gpdma"] # Nucleo | |||
| 12 | stm32c031c6 = ["embassy-stm32/stm32c031c6", "not-gpdma"] # Nucleo | 12 | stm32c031c6 = ["embassy-stm32/stm32c031c6", "not-gpdma"] # Nucleo |
| 13 | stm32g491re = ["embassy-stm32/stm32g491re", "not-gpdma"] # Nucleo | 13 | stm32g491re = ["embassy-stm32/stm32g491re", "not-gpdma"] # Nucleo |
| 14 | stm32h755zi = ["embassy-stm32/stm32h755zi-cm7", "not-gpdma"] # Nucleo | 14 | stm32h755zi = ["embassy-stm32/stm32h755zi-cm7", "not-gpdma"] # Nucleo |
| 15 | stm32wb55rg = ["embassy-stm32/stm32wb55rg", "not-gpdma", "ble" ] # Nucleo | 15 | stm32wb55rg = ["embassy-stm32/stm32wb55rg", "not-gpdma", "ble", "mac" ] # Nucleo |
| 16 | stm32h563zi = ["embassy-stm32/stm32h563zi"] # Nucleo | 16 | stm32h563zi = ["embassy-stm32/stm32h563zi"] # Nucleo |
| 17 | stm32u585ai = ["embassy-stm32/stm32u585ai"] # IoT board | 17 | stm32u585ai = ["embassy-stm32/stm32u585ai"] # IoT board |
| 18 | 18 | ||
| 19 | sdmmc = [] | 19 | sdmmc = [] |
| 20 | chrono = ["embassy-stm32/chrono", "dep:chrono"] | 20 | chrono = ["embassy-stm32/chrono", "dep:chrono"] |
| 21 | can = [] | 21 | can = [] |
| 22 | ble = ["dep:embassy-stm32-wpan"] | 22 | ble = ["dep:embassy-stm32-wpan", "embassy-stm32-wpan/ble"] |
| 23 | mac = ["dep:embassy-stm32-wpan", "embassy-stm32-wpan/mac"] | ||
| 24 | embassy-stm32-wpan = [] | ||
| 23 | not-gpdma = [] | 25 | not-gpdma = [] |
| 24 | 26 | ||
| 25 | [dependencies] | 27 | [dependencies] |
| @@ -27,7 +29,7 @@ teleprobe-meta = "1" | |||
| 27 | 29 | ||
| 28 | embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] } | 30 | embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] } |
| 29 | embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } | 31 | embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } |
| 30 | embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "tick-hz-32_768", "defmt-timestamp-uptime"] } | 32 | embassy-time = { version = "0.1.2", path = "../../embassy-time", features = ["defmt", "tick-hz-32_768", "defmt-timestamp-uptime"] } |
| 31 | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "unstable-pac", "memory-x", "time-driver-any"] } | 33 | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "unstable-pac", "memory-x", "time-driver-any"] } |
| 32 | embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } | 34 | embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } |
| 33 | embassy-stm32-wpan = { version = "0.1.0", path = "../../embassy-stm32-wpan", optional = true, features = ["defmt", "stm32wb55rg", "ble"] } | 35 | embassy-stm32-wpan = { version = "0.1.0", path = "../../embassy-stm32-wpan", optional = true, features = ["defmt", "stm32wb55rg", "ble"] } |
| @@ -38,25 +40,17 @@ defmt-rtt = "0.4" | |||
| 38 | cortex-m = { version = "0.7.6", features = ["critical-section-single-core"] } | 40 | cortex-m = { version = "0.7.6", features = ["critical-section-single-core"] } |
| 39 | cortex-m-rt = "0.7.0" | 41 | cortex-m-rt = "0.7.0" |
| 40 | embedded-hal = "0.2.6" | 42 | embedded-hal = "0.2.6" |
| 41 | embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-alpha.10" } | 43 | embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-alpha.11" } |
| 42 | embedded-hal-async = { version = "=0.2.0-alpha.1" } | 44 | embedded-hal-async = { version = "=0.2.0-alpha.2" } |
| 43 | panic-probe = { version = "0.3.0", features = ["print-defmt"] } | 45 | panic-probe = { version = "0.3.0", features = ["print-defmt"] } |
| 44 | rand_core = { version = "0.6", default-features = false } | 46 | rand_core = { version = "0.6", default-features = false } |
| 45 | rand_chacha = { version = "0.3", default-features = false } | 47 | rand_chacha = { version = "0.3", default-features = false } |
| 46 | 48 | ||
| 47 | chrono = { version = "^0.4", default-features = false, optional = true} | 49 | chrono = { version = "^0.4", default-features = false, optional = true} |
| 48 | 50 | ||
| 49 | [patch.crates-io] | ||
| 50 | stm32wb-hci = { git = "https://github.com/OueslatiGhaith/stm32wb-hci", rev = "9f663be"} | ||
| 51 | |||
| 52 | # BEGIN TESTS | 51 | # BEGIN TESTS |
| 53 | # Generated by gen_test.py. DO NOT EDIT. | 52 | # Generated by gen_test.py. DO NOT EDIT. |
| 54 | [[bin]] | 53 | [[bin]] |
| 55 | name = "tl_mbox" | ||
| 56 | path = "src/bin/tl_mbox.rs" | ||
| 57 | required-features = [ "ble",] | ||
| 58 | |||
| 59 | [[bin]] | ||
| 60 | name = "can" | 54 | name = "can" |
| 61 | path = "src/bin/can.rs" | 55 | path = "src/bin/can.rs" |
| 62 | required-features = [ "can",] | 56 | required-features = [ "can",] |
| @@ -106,6 +100,16 @@ name = "usart_rx_ringbuffered" | |||
| 106 | path = "src/bin/usart_rx_ringbuffered.rs" | 100 | path = "src/bin/usart_rx_ringbuffered.rs" |
| 107 | required-features = [ "not-gpdma",] | 101 | required-features = [ "not-gpdma",] |
| 108 | 102 | ||
| 103 | [[bin]] | ||
| 104 | name = "wpan_ble" | ||
| 105 | path = "src/bin/wpan_ble.rs" | ||
| 106 | required-features = [ "ble",] | ||
| 107 | |||
| 108 | [[bin]] | ||
| 109 | name = "wpan_mac" | ||
| 110 | path = "src/bin/wpan_mac.rs" | ||
| 111 | required-features = [ "mac",] | ||
| 112 | |||
| 109 | # END TESTS | 113 | # END TESTS |
| 110 | 114 | ||
| 111 | [profile.dev] | 115 | [profile.dev] |
diff --git a/tests/stm32/src/bin/can.rs b/tests/stm32/src/bin/can.rs index 33d63d546..8bdd3c24f 100644 --- a/tests/stm32/src/bin/can.rs +++ b/tests/stm32/src/bin/can.rs | |||
| @@ -43,10 +43,13 @@ async fn main(_spawner: Spawner) { | |||
| 43 | 43 | ||
| 44 | info!("Configuring can..."); | 44 | info!("Configuring can..."); |
| 45 | 45 | ||
| 46 | can.modify_filters().enable_bank(0, Fifo::Fifo0, Mask32::accept_all()); | 46 | can.as_mut() |
| 47 | .modify_filters() | ||
| 48 | .enable_bank(0, Fifo::Fifo0, Mask32::accept_all()); | ||
| 47 | 49 | ||
| 48 | can.set_bitrate(1_000_000); | 50 | can.set_bitrate(1_000_000); |
| 49 | can.modify_config() | 51 | can.as_mut() |
| 52 | .modify_config() | ||
| 50 | .set_loopback(true) // Receive own frames | 53 | .set_loopback(true) // Receive own frames |
| 51 | .set_silent(true) | 54 | .set_silent(true) |
| 52 | // .set_bit_timing(0x001c0003) | 55 | // .set_bit_timing(0x001c0003) |
diff --git a/tests/stm32/src/bin/gpio.rs b/tests/stm32/src/bin/gpio.rs index 67f44317e..aad174431 100644 --- a/tests/stm32/src/bin/gpio.rs +++ b/tests/stm32/src/bin/gpio.rs | |||
| @@ -40,14 +40,46 @@ async fn main(_spawner: Spawner) { | |||
| 40 | let b = Input::new(&mut b, Pull::None); | 40 | let b = Input::new(&mut b, Pull::None); |
| 41 | 41 | ||
| 42 | { | 42 | { |
| 43 | let _a = Output::new(&mut a, Level::Low, Speed::Low); | 43 | let a = Output::new(&mut a, Level::Low, Speed::Low); |
| 44 | delay(); | 44 | delay(); |
| 45 | assert!(b.is_low()); | 45 | assert!(b.is_low()); |
| 46 | assert!(!b.is_high()); | ||
| 47 | assert!(a.is_set_low()); | ||
| 48 | assert!(!a.is_set_high()); | ||
| 46 | } | 49 | } |
| 47 | { | 50 | { |
| 48 | let _a = Output::new(&mut a, Level::High, Speed::Low); | 51 | let mut a = Output::new(&mut a, Level::High, Speed::Low); |
| 49 | delay(); | 52 | delay(); |
| 53 | assert!(!b.is_low()); | ||
| 50 | assert!(b.is_high()); | 54 | assert!(b.is_high()); |
| 55 | assert!(!a.is_set_low()); | ||
| 56 | assert!(a.is_set_high()); | ||
| 57 | |||
| 58 | // Test is_set_low / is_set_high | ||
| 59 | a.set_low(); | ||
| 60 | delay(); | ||
| 61 | assert!(b.is_low()); | ||
| 62 | assert!(a.is_set_low()); | ||
| 63 | assert!(!a.is_set_high()); | ||
| 64 | |||
| 65 | a.set_high(); | ||
| 66 | delay(); | ||
| 67 | assert!(b.is_high()); | ||
| 68 | assert!(!a.is_set_low()); | ||
| 69 | assert!(a.is_set_high()); | ||
| 70 | |||
| 71 | // Test toggle | ||
| 72 | a.toggle(); | ||
| 73 | delay(); | ||
| 74 | assert!(b.is_low()); | ||
| 75 | assert!(a.is_set_low()); | ||
| 76 | assert!(!a.is_set_high()); | ||
| 77 | |||
| 78 | a.toggle(); | ||
| 79 | delay(); | ||
| 80 | assert!(b.is_high()); | ||
| 81 | assert!(!a.is_set_low()); | ||
| 82 | assert!(a.is_set_high()); | ||
| 51 | } | 83 | } |
| 52 | } | 84 | } |
| 53 | 85 | ||
diff --git a/tests/stm32/src/bin/rtc.rs b/tests/stm32/src/bin/rtc.rs index 582df5753..194b153d5 100644 --- a/tests/stm32/src/bin/rtc.rs +++ b/tests/stm32/src/bin/rtc.rs | |||
| @@ -1,3 +1,5 @@ | |||
| 1 | // required-features: chrono | ||
| 2 | |||
| 1 | #![no_std] | 3 | #![no_std] |
| 2 | #![no_main] | 4 | #![no_main] |
| 3 | #![feature(type_alias_impl_trait)] | 5 | #![feature(type_alias_impl_trait)] |
diff --git a/tests/stm32/src/bin/tl_mbox.rs b/tests/stm32/src/bin/wpan_ble.rs index af3832709..3ad8aca4e 100644 --- a/tests/stm32/src/bin/tl_mbox.rs +++ b/tests/stm32/src/bin/wpan_ble.rs | |||
| @@ -64,7 +64,7 @@ async fn main(spawner: Spawner) { | |||
| 64 | version_major, version_minor, subversion, sram2a_size, sram2b_size | 64 | version_major, version_minor, subversion, sram2a_size, sram2b_size |
| 65 | ); | 65 | ); |
| 66 | 66 | ||
| 67 | mbox.sys_subsystem.shci_c2_ble_init(Default::default()).await; | 67 | let _ = mbox.sys_subsystem.shci_c2_ble_init(Default::default()).await; |
| 68 | 68 | ||
| 69 | info!("resetting BLE..."); | 69 | info!("resetting BLE..."); |
| 70 | mbox.ble_subsystem.reset().await; | 70 | mbox.ble_subsystem.reset().await; |
diff --git a/tests/stm32/src/bin/wpan_mac.rs b/tests/stm32/src/bin/wpan_mac.rs new file mode 100644 index 000000000..cfa0aca3b --- /dev/null +++ b/tests/stm32/src/bin/wpan_mac.rs | |||
| @@ -0,0 +1,108 @@ | |||
| 1 | // required-features: mac | ||
| 2 | |||
| 3 | #![no_std] | ||
| 4 | #![no_main] | ||
| 5 | #![feature(type_alias_impl_trait)] | ||
| 6 | #[path = "../common.rs"] | ||
| 7 | mod common; | ||
| 8 | |||
| 9 | use common::*; | ||
| 10 | use embassy_executor::Spawner; | ||
| 11 | use embassy_stm32::bind_interrupts; | ||
| 12 | use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler}; | ||
| 13 | use embassy_stm32_wpan::mac::commands::{AssociateRequest, GetRequest, ResetRequest, SetRequest}; | ||
| 14 | use embassy_stm32_wpan::mac::event::MacEvent; | ||
| 15 | use embassy_stm32_wpan::mac::typedefs::{ | ||
| 16 | AddressMode, Capabilities, KeyIdMode, MacAddress, MacChannel, PanId, PibId, SecurityLevel, | ||
| 17 | }; | ||
| 18 | use embassy_stm32_wpan::sub::mm; | ||
| 19 | use embassy_stm32_wpan::TlMbox; | ||
| 20 | use {defmt_rtt as _, panic_probe as _}; | ||
| 21 | |||
| 22 | bind_interrupts!(struct Irqs{ | ||
| 23 | IPCC_C1_RX => ReceiveInterruptHandler; | ||
| 24 | IPCC_C1_TX => TransmitInterruptHandler; | ||
| 25 | }); | ||
| 26 | |||
| 27 | #[embassy_executor::task] | ||
| 28 | async fn run_mm_queue(memory_manager: mm::MemoryManager) { | ||
| 29 | memory_manager.run_queue().await; | ||
| 30 | } | ||
| 31 | |||
| 32 | #[embassy_executor::main] | ||
| 33 | async fn main(spawner: Spawner) { | ||
| 34 | let p = embassy_stm32::init(config()); | ||
| 35 | info!("Hello World!"); | ||
| 36 | |||
| 37 | let config = Config::default(); | ||
| 38 | let mbox = TlMbox::init(p.IPCC, Irqs, config); | ||
| 39 | |||
| 40 | spawner.spawn(run_mm_queue(mbox.mm_subsystem)).unwrap(); | ||
| 41 | |||
| 42 | let sys_event = mbox.sys_subsystem.read().await; | ||
| 43 | info!("sys event: {}", sys_event.payload()); | ||
| 44 | |||
| 45 | core::mem::drop(sys_event); | ||
| 46 | |||
| 47 | let result = mbox.sys_subsystem.shci_c2_mac_802_15_4_init().await; | ||
| 48 | info!("initialized mac: {}", result); | ||
| 49 | |||
| 50 | info!("resetting"); | ||
| 51 | mbox.mac_subsystem | ||
| 52 | .send_command(&ResetRequest { set_default_pib: true }) | ||
| 53 | .await | ||
| 54 | .unwrap(); | ||
| 55 | let evt = mbox.mac_subsystem.read().await; | ||
| 56 | info!("{:#x}", evt); | ||
| 57 | |||
| 58 | info!("setting extended address"); | ||
| 59 | let extended_address: u64 = 0xACDE480000000002; | ||
| 60 | mbox.mac_subsystem | ||
| 61 | .send_command(&SetRequest { | ||
| 62 | pib_attribute_ptr: &extended_address as *const _ as *const u8, | ||
| 63 | pib_attribute: PibId::ExtendedAddress, | ||
| 64 | }) | ||
| 65 | .await | ||
| 66 | .unwrap(); | ||
| 67 | let evt = mbox.mac_subsystem.read().await; | ||
| 68 | info!("{:#x}", evt); | ||
| 69 | |||
| 70 | info!("getting extended address"); | ||
| 71 | mbox.mac_subsystem | ||
| 72 | .send_command(&GetRequest { | ||
| 73 | pib_attribute: PibId::ExtendedAddress, | ||
| 74 | }) | ||
| 75 | .await | ||
| 76 | .unwrap(); | ||
| 77 | let evt = mbox.mac_subsystem.read().await; | ||
| 78 | info!("{:#x}", evt); | ||
| 79 | |||
| 80 | if let Ok(MacEvent::MlmeGetCnf(evt)) = evt { | ||
| 81 | if evt.pib_attribute_value_len == 8 { | ||
| 82 | let value = unsafe { core::ptr::read_unaligned(evt.pib_attribute_value_ptr as *const u64) }; | ||
| 83 | |||
| 84 | info!("value {:#x}", value) | ||
| 85 | } | ||
| 86 | } | ||
| 87 | |||
| 88 | info!("assocation request"); | ||
| 89 | let a = AssociateRequest { | ||
| 90 | channel_number: MacChannel::Channel16, | ||
| 91 | channel_page: 0, | ||
| 92 | coord_addr_mode: AddressMode::Short, | ||
| 93 | coord_address: MacAddress { short: [34, 17] }, | ||
| 94 | capability_information: Capabilities::ALLOCATE_ADDRESS, | ||
| 95 | coord_pan_id: PanId([0x1A, 0xAA]), | ||
| 96 | security_level: SecurityLevel::Unsecure, | ||
| 97 | key_id_mode: KeyIdMode::Implicite, | ||
| 98 | key_source: [0; 8], | ||
| 99 | key_index: 152, | ||
| 100 | }; | ||
| 101 | info!("{}", a); | ||
| 102 | mbox.mac_subsystem.send_command(&a).await.unwrap(); | ||
| 103 | let evt = mbox.mac_subsystem.read().await; | ||
| 104 | info!("{:#x}", evt); | ||
| 105 | |||
| 106 | info!("Test OK"); | ||
| 107 | cortex_m::asm::bkpt(); | ||
| 108 | } | ||
