diff options
| -rw-r--r-- | embassy-boot/nrf/src/lib.rs | 26 | ||||
| -rw-r--r-- | embassy-net-tuntap/Cargo.toml | 19 | ||||
| -rw-r--r-- | embassy-net-tuntap/README.md | 17 | ||||
| -rw-r--r-- | embassy-net-tuntap/src/lib.rs (renamed from examples/std/src/tuntap.rs) | 1 | ||||
| -rw-r--r-- | embassy-net/README.md | 2 | ||||
| -rw-r--r-- | embassy-rp/src/adc.rs | 210 | ||||
| -rw-r--r-- | embassy-rp/src/gpio.rs | 61 | ||||
| -rw-r--r-- | embassy-rp/src/lib.rs | 1 | ||||
| -rw-r--r-- | examples/rp/src/bin/adc.rs | 11 | ||||
| -rw-r--r-- | examples/std/Cargo.toml | 3 | ||||
| -rw-r--r-- | examples/std/src/bin/net.rs | 5 | ||||
| -rw-r--r-- | examples/std/src/bin/net_dns.rs | 5 | ||||
| -rw-r--r-- | examples/std/src/bin/net_udp.rs | 5 | ||||
| -rw-r--r-- | examples/std/src/bin/tcp_accept.rs | 5 | ||||
| -rw-r--r-- | tests/rp/src/bin/adc.rs | 73 |
15 files changed, 339 insertions, 105 deletions
diff --git a/embassy-boot/nrf/src/lib.rs b/embassy-boot/nrf/src/lib.rs index bb702073c..65f57fcd1 100644 --- a/embassy-boot/nrf/src/lib.rs +++ b/embassy-boot/nrf/src/lib.rs | |||
| @@ -6,7 +6,7 @@ mod fmt; | |||
| 6 | #[cfg(feature = "nightly")] | 6 | #[cfg(feature = "nightly")] |
| 7 | pub use embassy_boot::FirmwareUpdater; | 7 | pub use embassy_boot::FirmwareUpdater; |
| 8 | pub use embassy_boot::{AlignedBuffer, BlockingFirmwareUpdater, BootLoaderConfig, FirmwareUpdaterConfig}; | 8 | pub use embassy_boot::{AlignedBuffer, BlockingFirmwareUpdater, BootLoaderConfig, FirmwareUpdaterConfig}; |
| 9 | use embassy_nrf::nvmc::{Nvmc, PAGE_SIZE}; | 9 | use embassy_nrf::nvmc::PAGE_SIZE; |
| 10 | use embassy_nrf::peripherals::WDT; | 10 | use embassy_nrf::peripherals::WDT; |
| 11 | use embassy_nrf::wdt; | 11 | use embassy_nrf::wdt; |
| 12 | use embedded_storage::nor_flash::{ErrorType, NorFlash, ReadNorFlash}; | 12 | use embedded_storage::nor_flash::{ErrorType, NorFlash, ReadNorFlash}; |
| @@ -104,15 +104,15 @@ impl<ACTIVE: NorFlash, DFU: NorFlash, STATE: NorFlash, const BUFFER_SIZE: usize> | |||
| 104 | } | 104 | } |
| 105 | } | 105 | } |
| 106 | 106 | ||
| 107 | /// A flash implementation that wraps NVMC and will pet a watchdog when touching flash. | 107 | /// A flash implementation that wraps any flash and will pet a watchdog when touching flash. |
| 108 | pub struct WatchdogFlash<'d> { | 108 | pub struct WatchdogFlash<FLASH> { |
| 109 | flash: Nvmc<'d>, | 109 | flash: FLASH, |
| 110 | wdt: wdt::WatchdogHandle, | 110 | wdt: wdt::WatchdogHandle, |
| 111 | } | 111 | } |
| 112 | 112 | ||
| 113 | impl<'d> WatchdogFlash<'d> { | 113 | impl<FLASH> WatchdogFlash<FLASH> { |
| 114 | /// Start a new watchdog with a given flash and WDT peripheral and a timeout | 114 | /// Start a new watchdog with a given flash and WDT peripheral and a timeout |
| 115 | pub fn start(flash: Nvmc<'d>, wdt: WDT, config: wdt::Config) -> Self { | 115 | pub fn start(flash: FLASH, wdt: WDT, config: wdt::Config) -> Self { |
| 116 | let (_wdt, [wdt]) = match wdt::Watchdog::try_new(wdt, config) { | 116 | let (_wdt, [wdt]) = match wdt::Watchdog::try_new(wdt, config) { |
| 117 | Ok(x) => x, | 117 | Ok(x) => x, |
| 118 | Err(_) => { | 118 | Err(_) => { |
| @@ -127,13 +127,13 @@ impl<'d> WatchdogFlash<'d> { | |||
| 127 | } | 127 | } |
| 128 | } | 128 | } |
| 129 | 129 | ||
| 130 | impl<'d> ErrorType for WatchdogFlash<'d> { | 130 | impl<FLASH: ErrorType> ErrorType for WatchdogFlash<FLASH> { |
| 131 | type Error = <Nvmc<'d> as ErrorType>::Error; | 131 | type Error = FLASH::Error; |
| 132 | } | 132 | } |
| 133 | 133 | ||
| 134 | impl<'d> NorFlash for WatchdogFlash<'d> { | 134 | impl<FLASH: NorFlash> NorFlash for WatchdogFlash<FLASH> { |
| 135 | const WRITE_SIZE: usize = <Nvmc<'d> as NorFlash>::WRITE_SIZE; | 135 | const WRITE_SIZE: usize = FLASH::WRITE_SIZE; |
| 136 | const ERASE_SIZE: usize = <Nvmc<'d> as NorFlash>::ERASE_SIZE; | 136 | const ERASE_SIZE: usize = FLASH::ERASE_SIZE; |
| 137 | 137 | ||
| 138 | fn erase(&mut self, from: u32, to: u32) -> Result<(), Self::Error> { | 138 | fn erase(&mut self, from: u32, to: u32) -> Result<(), Self::Error> { |
| 139 | self.wdt.pet(); | 139 | self.wdt.pet(); |
| @@ -145,8 +145,8 @@ impl<'d> NorFlash for WatchdogFlash<'d> { | |||
| 145 | } | 145 | } |
| 146 | } | 146 | } |
| 147 | 147 | ||
| 148 | impl<'d> ReadNorFlash for WatchdogFlash<'d> { | 148 | impl<FLASH: ReadNorFlash> ReadNorFlash for WatchdogFlash<FLASH> { |
| 149 | const READ_SIZE: usize = <Nvmc<'d> as ReadNorFlash>::READ_SIZE; | 149 | const READ_SIZE: usize = FLASH::READ_SIZE; |
| 150 | fn read(&mut self, offset: u32, data: &mut [u8]) -> Result<(), Self::Error> { | 150 | fn read(&mut self, offset: u32, data: &mut [u8]) -> Result<(), Self::Error> { |
| 151 | self.wdt.pet(); | 151 | self.wdt.pet(); |
| 152 | self.flash.read(offset, data) | 152 | self.flash.read(offset, data) |
diff --git a/embassy-net-tuntap/Cargo.toml b/embassy-net-tuntap/Cargo.toml new file mode 100644 index 000000000..08d309680 --- /dev/null +++ b/embassy-net-tuntap/Cargo.toml | |||
| @@ -0,0 +1,19 @@ | |||
| 1 | [package] | ||
| 2 | name = "embassy-net-tuntap" | ||
| 3 | version = "0.1.0" | ||
| 4 | description = "embassy-net driver for Linux TUN/TAP interfaces." | ||
| 5 | keywords = ["embedded", "tuntap", "embassy-net", "embedded-hal-async", "ethernet", "async"] | ||
| 6 | categories = ["embedded", "hardware-support", "no-std", "network-programming", "async"] | ||
| 7 | license = "MIT OR Apache-2.0" | ||
| 8 | edition = "2021" | ||
| 9 | |||
| 10 | [dependencies] | ||
| 11 | embassy-net-driver = { version = "0.1.0", path = "../embassy-net-driver" } | ||
| 12 | async-io = "1.6.0" | ||
| 13 | log = "0.4.14" | ||
| 14 | libc = "0.2.101" | ||
| 15 | |||
| 16 | [package.metadata.embassy_docs] | ||
| 17 | src_base = "https://github.com/embassy-rs/embassy/blob/embassy-net-tuntap-v$VERSION/embassy-net-tuntap/src/" | ||
| 18 | src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-net-tuntap/src/" | ||
| 19 | target = "thumbv7em-none-eabi" \ No newline at end of file | ||
diff --git a/embassy-net-tuntap/README.md b/embassy-net-tuntap/README.md new file mode 100644 index 000000000..c5d9e746c --- /dev/null +++ b/embassy-net-tuntap/README.md | |||
| @@ -0,0 +1,17 @@ | |||
| 1 | # `embassy-net` integration for Linux TUN/TAP interfaces. | ||
| 2 | |||
| 3 | [`embassy-net`](https://crates.io/crates/embassy-net) integration for for Linux TUN (IP medium) and TAP (Ethernet medium) interfaces. | ||
| 4 | |||
| 5 | ## Interoperability | ||
| 6 | |||
| 7 | This crate can run on any executor. | ||
| 8 | |||
| 9 | ## License | ||
| 10 | |||
| 11 | This work is licensed under either of | ||
| 12 | |||
| 13 | - Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or | ||
| 14 | http://www.apache.org/licenses/LICENSE-2.0) | ||
| 15 | - MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) | ||
| 16 | |||
| 17 | at your option. | ||
diff --git a/examples/std/src/tuntap.rs b/embassy-net-tuntap/src/lib.rs index 167c3da5f..75c54c487 100644 --- a/examples/std/src/tuntap.rs +++ b/embassy-net-tuntap/src/lib.rs | |||
| @@ -19,6 +19,7 @@ const ETHERNET_HEADER_LEN: usize = 14; | |||
| 19 | 19 | ||
| 20 | #[repr(C)] | 20 | #[repr(C)] |
| 21 | #[derive(Debug)] | 21 | #[derive(Debug)] |
| 22 | #[allow(non_camel_case_types)] | ||
| 22 | struct ifreq { | 23 | struct ifreq { |
| 23 | ifr_name: [libc::c_char; libc::IF_NAMESIZE], | 24 | ifr_name: [libc::c_char; libc::IF_NAMESIZE], |
| 24 | ifr_data: libc::c_int, /* ifr_ifindex or ifr_mtu */ | 25 | ifr_data: libc::c_int, /* ifr_ifindex or ifr_mtu */ |
diff --git a/embassy-net/README.md b/embassy-net/README.md index 48f9fd832..811321ca4 100644 --- a/embassy-net/README.md +++ b/embassy-net/README.md | |||
| @@ -49,7 +49,7 @@ trait has not had breaking changes. | |||
| 49 | 49 | ||
| 50 | This crate can run on any executor. | 50 | This crate can run on any executor. |
| 51 | 51 | ||
| 52 | [`embassy-time`](https://crates.io/crates/embassy-net-driver) is used for timekeeping and timeouts. You must | 52 | [`embassy-time`](https://crates.io/crates/embassy-time) is used for timekeeping and timeouts. You must |
| 53 | link an `embassy-time` driver in your project to use this crate. | 53 | link an `embassy-time` driver in your project to use this crate. |
| 54 | 54 | ||
| 55 | ## License | 55 | ## License |
diff --git a/embassy-rp/src/adc.rs b/embassy-rp/src/adc.rs index 4fba31169..bac455743 100644 --- a/embassy-rp/src/adc.rs +++ b/embassy-rp/src/adc.rs | |||
| @@ -1,5 +1,6 @@ | |||
| 1 | use core::future::poll_fn; | 1 | use core::future::poll_fn; |
| 2 | use core::marker::PhantomData; | 2 | use core::marker::PhantomData; |
| 3 | use core::mem; | ||
| 3 | use core::sync::atomic::{compiler_fence, Ordering}; | 4 | use core::sync::atomic::{compiler_fence, Ordering}; |
| 4 | use core::task::Poll; | 5 | use core::task::Poll; |
| 5 | 6 | ||
| @@ -10,8 +11,8 @@ use crate::gpio::sealed::Pin as GpioPin; | |||
| 10 | use crate::gpio::{self, AnyPin, Pull}; | 11 | use crate::gpio::{self, AnyPin, Pull}; |
| 11 | use crate::interrupt::typelevel::Binding; | 12 | use crate::interrupt::typelevel::Binding; |
| 12 | use crate::interrupt::InterruptExt; | 13 | use crate::interrupt::InterruptExt; |
| 13 | use crate::peripherals::ADC; | 14 | use crate::peripherals::{ADC, ADC_TEMP_SENSOR}; |
| 14 | use crate::{interrupt, pac, peripherals, Peripheral}; | 15 | use crate::{dma, interrupt, pac, peripherals, Peripheral, RegExt}; |
| 15 | 16 | ||
| 16 | static WAKER: AtomicWaker = AtomicWaker::new(); | 17 | static WAKER: AtomicWaker = AtomicWaker::new(); |
| 17 | 18 | ||
| @@ -24,12 +25,15 @@ impl Default for Config { | |||
| 24 | } | 25 | } |
| 25 | } | 26 | } |
| 26 | 27 | ||
| 27 | pub struct Pin<'p> { | 28 | enum Source<'p> { |
| 28 | pin: PeripheralRef<'p, AnyPin>, | 29 | Pin(PeripheralRef<'p, AnyPin>), |
| 30 | TempSensor(PeripheralRef<'p, ADC_TEMP_SENSOR>), | ||
| 29 | } | 31 | } |
| 30 | 32 | ||
| 31 | impl<'p> Pin<'p> { | 33 | pub struct Channel<'p>(Source<'p>); |
| 32 | pub fn new(pin: impl Peripheral<P = impl AdcPin + 'p> + 'p, pull: Pull) -> Self { | 34 | |
| 35 | impl<'p> Channel<'p> { | ||
| 36 | pub fn new_pin(pin: impl Peripheral<P = impl AdcPin + 'p> + 'p, pull: Pull) -> Self { | ||
| 33 | into_ref!(pin); | 37 | into_ref!(pin); |
| 34 | pin.pad_ctrl().modify(|w| { | 38 | pin.pad_ctrl().modify(|w| { |
| 35 | // manual says: | 39 | // manual says: |
| @@ -42,24 +46,55 @@ impl<'p> Pin<'p> { | |||
| 42 | w.set_pue(pull == Pull::Up); | 46 | w.set_pue(pull == Pull::Up); |
| 43 | w.set_pde(pull == Pull::Down); | 47 | w.set_pde(pull == Pull::Down); |
| 44 | }); | 48 | }); |
| 45 | Self { pin: pin.map_into() } | 49 | Self(Source::Pin(pin.map_into())) |
| 50 | } | ||
| 51 | |||
| 52 | pub fn new_temp_sensor(s: impl Peripheral<P = ADC_TEMP_SENSOR> + 'p) -> Self { | ||
| 53 | let r = pac::ADC; | ||
| 54 | r.cs().write_set(|w| w.set_ts_en(true)); | ||
| 55 | Self(Source::TempSensor(s.into_ref())) | ||
| 46 | } | 56 | } |
| 47 | 57 | ||
| 48 | fn channel(&self) -> u8 { | 58 | fn channel(&self) -> u8 { |
| 49 | // this requires adc pins to be sequential and matching the adc channels, | 59 | match &self.0 { |
| 50 | // which is the case for rp2040 | 60 | // this requires adc pins to be sequential and matching the adc channels, |
| 51 | self.pin._pin() - 26 | 61 | // which is the case for rp2040 |
| 62 | Source::Pin(p) => p._pin() - 26, | ||
| 63 | Source::TempSensor(_) => 4, | ||
| 64 | } | ||
| 52 | } | 65 | } |
| 53 | } | 66 | } |
| 54 | 67 | ||
| 55 | impl<'d> Drop for Pin<'d> { | 68 | impl<'p> Drop for Source<'p> { |
| 56 | fn drop(&mut self) { | 69 | fn drop(&mut self) { |
| 57 | self.pin.pad_ctrl().modify(|w| { | 70 | match self { |
| 58 | w.set_ie(true); | 71 | Source::Pin(p) => { |
| 59 | w.set_od(false); | 72 | p.pad_ctrl().modify(|w| { |
| 60 | w.set_pue(false); | 73 | w.set_ie(true); |
| 61 | w.set_pde(true); | 74 | w.set_od(false); |
| 62 | }); | 75 | w.set_pue(false); |
| 76 | w.set_pde(true); | ||
| 77 | }); | ||
| 78 | } | ||
| 79 | Source::TempSensor(_) => { | ||
| 80 | pac::ADC.cs().write_clear(|w| w.set_ts_en(true)); | ||
| 81 | } | ||
| 82 | } | ||
| 83 | } | ||
| 84 | } | ||
| 85 | |||
| 86 | #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug, Default)] | ||
| 87 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 88 | #[repr(transparent)] | ||
| 89 | pub struct Sample(u16); | ||
| 90 | |||
| 91 | impl Sample { | ||
| 92 | pub fn good(&self) -> bool { | ||
| 93 | self.0 < 0x8000 | ||
| 94 | } | ||
| 95 | |||
| 96 | pub fn value(&self) -> u16 { | ||
| 97 | self.0 & !0x8000 | ||
| 63 | } | 98 | } |
| 64 | } | 99 | } |
| 65 | 100 | ||
| @@ -115,10 +150,10 @@ impl<'d, M: Mode> Adc<'d, M> { | |||
| 115 | while !r.cs().read().ready() {} | 150 | while !r.cs().read().ready() {} |
| 116 | } | 151 | } |
| 117 | 152 | ||
| 118 | fn sample_blocking(channel: u8) -> Result<u16, Error> { | 153 | pub fn blocking_read(&mut self, ch: &mut Channel) -> Result<u16, Error> { |
| 119 | let r = Self::regs(); | 154 | let r = Self::regs(); |
| 120 | r.cs().modify(|w| { | 155 | r.cs().modify(|w| { |
| 121 | w.set_ainsel(channel); | 156 | w.set_ainsel(ch.channel()); |
| 122 | w.set_start_once(true); | 157 | w.set_start_once(true); |
| 123 | w.set_err(true); | 158 | w.set_err(true); |
| 124 | }); | 159 | }); |
| @@ -128,19 +163,6 @@ impl<'d, M: Mode> Adc<'d, M> { | |||
| 128 | false => Ok(r.result().read().result().into()), | 163 | false => Ok(r.result().read().result().into()), |
| 129 | } | 164 | } |
| 130 | } | 165 | } |
| 131 | |||
| 132 | pub fn blocking_read(&mut self, pin: &mut Pin) -> Result<u16, Error> { | ||
| 133 | Self::sample_blocking(pin.channel()) | ||
| 134 | } | ||
| 135 | |||
| 136 | pub fn blocking_read_temperature(&mut self) -> Result<u16, Error> { | ||
| 137 | let r = Self::regs(); | ||
| 138 | r.cs().modify(|w| w.set_ts_en(true)); | ||
| 139 | while !r.cs().read().ready() {} | ||
| 140 | let result = Self::sample_blocking(4); | ||
| 141 | r.cs().modify(|w| w.set_ts_en(false)); | ||
| 142 | result | ||
| 143 | } | ||
| 144 | } | 166 | } |
| 145 | 167 | ||
| 146 | impl<'d> Adc<'d, Async> { | 168 | impl<'d> Adc<'d, Async> { |
| @@ -172,10 +194,10 @@ impl<'d> Adc<'d, Async> { | |||
| 172 | .await; | 194 | .await; |
| 173 | } | 195 | } |
| 174 | 196 | ||
| 175 | async fn sample_async(channel: u8) -> Result<u16, Error> { | 197 | pub async fn read(&mut self, ch: &mut Channel<'_>) -> Result<u16, Error> { |
| 176 | let r = Self::regs(); | 198 | let r = Self::regs(); |
| 177 | r.cs().modify(|w| { | 199 | r.cs().modify(|w| { |
| 178 | w.set_ainsel(channel); | 200 | w.set_ainsel(ch.channel()); |
| 179 | w.set_start_once(true); | 201 | w.set_start_once(true); |
| 180 | w.set_err(true); | 202 | w.set_err(true); |
| 181 | }); | 203 | }); |
| @@ -186,19 +208,89 @@ impl<'d> Adc<'d, Async> { | |||
| 186 | } | 208 | } |
| 187 | } | 209 | } |
| 188 | 210 | ||
| 189 | pub async fn read(&mut self, pin: &mut Pin<'_>) -> Result<u16, Error> { | 211 | async fn read_many_inner<W: dma::Word>( |
| 190 | Self::sample_async(pin.channel()).await | 212 | &mut self, |
| 191 | } | 213 | ch: &mut Channel<'_>, |
| 192 | 214 | buf: &mut [W], | |
| 193 | pub async fn read_temperature(&mut self) -> Result<u16, Error> { | 215 | fcs_err: bool, |
| 216 | dma: impl Peripheral<P = impl dma::Channel>, | ||
| 217 | ) -> Result<(), Error> { | ||
| 194 | let r = Self::regs(); | 218 | let r = Self::regs(); |
| 195 | r.cs().modify(|w| w.set_ts_en(true)); | 219 | // clear previous errors and set channel |
| 196 | if !r.cs().read().ready() { | 220 | r.cs().modify(|w| { |
| 197 | Self::wait_for_ready().await; | 221 | w.set_ainsel(ch.channel()); |
| 222 | w.set_err_sticky(true); // clear previous errors | ||
| 223 | w.set_start_many(false); | ||
| 224 | }); | ||
| 225 | // wait for previous conversions and drain fifo. an earlier batch read may have | ||
| 226 | // been cancelled, leaving the adc running. | ||
| 227 | while !r.cs().read().ready() {} | ||
| 228 | while !r.fcs().read().empty() { | ||
| 229 | r.fifo().read(); | ||
| 230 | } | ||
| 231 | |||
| 232 | // set up fifo for dma | ||
| 233 | r.fcs().write(|w| { | ||
| 234 | w.set_thresh(1); | ||
| 235 | w.set_dreq_en(true); | ||
| 236 | w.set_shift(mem::size_of::<W>() == 1); | ||
| 237 | w.set_en(true); | ||
| 238 | w.set_err(fcs_err); | ||
| 239 | }); | ||
| 240 | |||
| 241 | // reset dma config on drop, regardless of whether it was a future being cancelled | ||
| 242 | // or the method returning normally. | ||
| 243 | struct ResetDmaConfig; | ||
| 244 | impl Drop for ResetDmaConfig { | ||
| 245 | fn drop(&mut self) { | ||
| 246 | pac::ADC.cs().write_clear(|w| w.set_start_many(true)); | ||
| 247 | while !pac::ADC.cs().read().ready() {} | ||
| 248 | pac::ADC.fcs().write_clear(|w| { | ||
| 249 | w.set_dreq_en(true); | ||
| 250 | w.set_shift(true); | ||
| 251 | w.set_en(true); | ||
| 252 | }); | ||
| 253 | } | ||
| 254 | } | ||
| 255 | let auto_reset = ResetDmaConfig; | ||
| 256 | |||
| 257 | let dma = unsafe { dma::read(dma, r.fifo().as_ptr() as *const W, buf as *mut [W], 36) }; | ||
| 258 | // start conversions and wait for dma to finish. we can't report errors early | ||
| 259 | // because there's no interrupt to signal them, and inspecting every element | ||
| 260 | // of the fifo is too costly to do here. | ||
| 261 | r.cs().write_set(|w| w.set_start_many(true)); | ||
| 262 | dma.await; | ||
| 263 | mem::drop(auto_reset); | ||
| 264 | // we can't report errors before the conversions have ended since no interrupt | ||
| 265 | // exists to report them early, and since they're exceedingly rare we probably don't | ||
| 266 | // want to anyway. | ||
| 267 | match r.cs().read().err_sticky() { | ||
| 268 | false => Ok(()), | ||
| 269 | true => Err(Error::ConversionFailed), | ||
| 198 | } | 270 | } |
| 199 | let result = Self::sample_async(4).await; | 271 | } |
| 200 | r.cs().modify(|w| w.set_ts_en(false)); | 272 | |
| 201 | result | 273 | #[inline] |
| 274 | pub async fn read_many<S: AdcSample>( | ||
| 275 | &mut self, | ||
| 276 | ch: &mut Channel<'_>, | ||
| 277 | buf: &mut [S], | ||
| 278 | dma: impl Peripheral<P = impl dma::Channel>, | ||
| 279 | ) -> Result<(), Error> { | ||
| 280 | self.read_many_inner(ch, buf, false, dma).await | ||
| 281 | } | ||
| 282 | |||
| 283 | #[inline] | ||
| 284 | pub async fn read_many_raw( | ||
| 285 | &mut self, | ||
| 286 | ch: &mut Channel<'_>, | ||
| 287 | buf: &mut [Sample], | ||
| 288 | dma: impl Peripheral<P = impl dma::Channel>, | ||
| 289 | ) { | ||
| 290 | // errors are reported in individual samples | ||
| 291 | let _ = self | ||
| 292 | .read_many_inner(ch, unsafe { mem::transmute::<_, &mut [u16]>(buf) }, true, dma) | ||
| 293 | .await; | ||
| 202 | } | 294 | } |
| 203 | } | 295 | } |
| 204 | 296 | ||
| @@ -223,21 +315,26 @@ impl interrupt::typelevel::Handler<interrupt::typelevel::ADC_IRQ_FIFO> for Inter | |||
| 223 | } | 315 | } |
| 224 | 316 | ||
| 225 | mod sealed { | 317 | mod sealed { |
| 226 | pub trait AdcPin: crate::gpio::sealed::Pin { | 318 | pub trait AdcSample: crate::dma::Word {} |
| 227 | fn channel(&mut self) -> u8; | 319 | |
| 228 | } | 320 | pub trait AdcChannel {} |
| 229 | } | 321 | } |
| 230 | 322 | ||
| 231 | pub trait AdcPin: sealed::AdcPin + gpio::Pin {} | 323 | pub trait AdcSample: sealed::AdcSample {} |
| 324 | |||
| 325 | impl sealed::AdcSample for u16 {} | ||
| 326 | impl AdcSample for u16 {} | ||
| 327 | |||
| 328 | impl sealed::AdcSample for u8 {} | ||
| 329 | impl AdcSample for u8 {} | ||
| 330 | |||
| 331 | pub trait AdcChannel: sealed::AdcChannel {} | ||
| 332 | pub trait AdcPin: AdcChannel + gpio::Pin {} | ||
| 232 | 333 | ||
| 233 | macro_rules! impl_pin { | 334 | macro_rules! impl_pin { |
| 234 | ($pin:ident, $channel:expr) => { | 335 | ($pin:ident, $channel:expr) => { |
| 235 | impl sealed::AdcPin for peripherals::$pin { | 336 | impl sealed::AdcChannel for peripherals::$pin {} |
| 236 | fn channel(&mut self) -> u8 { | 337 | impl AdcChannel for peripherals::$pin {} |
| 237 | $channel | ||
| 238 | } | ||
| 239 | } | ||
| 240 | |||
| 241 | impl AdcPin for peripherals::$pin {} | 338 | impl AdcPin for peripherals::$pin {} |
| 242 | }; | 339 | }; |
| 243 | } | 340 | } |
| @@ -246,3 +343,6 @@ impl_pin!(PIN_26, 0); | |||
| 246 | impl_pin!(PIN_27, 1); | 343 | impl_pin!(PIN_27, 1); |
| 247 | impl_pin!(PIN_28, 2); | 344 | impl_pin!(PIN_28, 2); |
| 248 | impl_pin!(PIN_29, 3); | 345 | impl_pin!(PIN_29, 3); |
| 346 | |||
| 347 | impl sealed::AdcChannel for peripherals::ADC_TEMP_SENSOR {} | ||
| 348 | impl AdcChannel for peripherals::ADC_TEMP_SENSOR {} | ||
diff --git a/embassy-rp/src/gpio.rs b/embassy-rp/src/gpio.rs index 73e893523..ad9d4262d 100644 --- a/embassy-rp/src/gpio.rs +++ b/embassy-rp/src/gpio.rs | |||
| @@ -75,6 +75,15 @@ pub enum Bank { | |||
| 75 | Qspi = 1, | 75 | Qspi = 1, |
| 76 | } | 76 | } |
| 77 | 77 | ||
| 78 | #[derive(Debug, Eq, PartialEq, Copy, Clone, Default)] | ||
| 79 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 80 | pub struct DormantWakeConfig { | ||
| 81 | pub edge_high: bool, | ||
| 82 | pub edge_low: bool, | ||
| 83 | pub level_high: bool, | ||
| 84 | pub level_low: bool, | ||
| 85 | } | ||
| 86 | |||
| 78 | pub struct Input<'d, T: Pin> { | 87 | pub struct Input<'d, T: Pin> { |
| 79 | pin: Flex<'d, T>, | 88 | pin: Flex<'d, T>, |
| 80 | } | 89 | } |
| @@ -128,6 +137,11 @@ impl<'d, T: Pin> Input<'d, T> { | |||
| 128 | pub async fn wait_for_any_edge(&mut self) { | 137 | pub async fn wait_for_any_edge(&mut self) { |
| 129 | self.pin.wait_for_any_edge().await; | 138 | self.pin.wait_for_any_edge().await; |
| 130 | } | 139 | } |
| 140 | |||
| 141 | #[inline] | ||
| 142 | pub fn dormant_wake(&mut self, cfg: DormantWakeConfig) -> DormantWake<T> { | ||
| 143 | self.pin.dormant_wake(cfg) | ||
| 144 | } | ||
| 131 | } | 145 | } |
| 132 | 146 | ||
| 133 | /// Interrupt trigger levels. | 147 | /// Interrupt trigger levels. |
| @@ -639,15 +653,62 @@ impl<'d, T: Pin> Flex<'d, T> { | |||
| 639 | pub async fn wait_for_any_edge(&mut self) { | 653 | pub async fn wait_for_any_edge(&mut self) { |
| 640 | InputFuture::new(&mut self.pin, InterruptTrigger::AnyEdge).await; | 654 | InputFuture::new(&mut self.pin, InterruptTrigger::AnyEdge).await; |
| 641 | } | 655 | } |
| 656 | |||
| 657 | #[inline] | ||
| 658 | pub fn dormant_wake(&mut self, cfg: DormantWakeConfig) -> DormantWake<T> { | ||
| 659 | let idx = self.pin._pin() as usize; | ||
| 660 | self.pin.io().intr(idx / 8).write(|w| { | ||
| 661 | w.set_edge_high(idx % 8, cfg.edge_high); | ||
| 662 | w.set_edge_low(idx % 8, cfg.edge_low); | ||
| 663 | }); | ||
| 664 | self.pin.io().int_dormant_wake().inte(idx / 8).write_set(|w| { | ||
| 665 | w.set_edge_high(idx % 8, cfg.edge_high); | ||
| 666 | w.set_edge_low(idx % 8, cfg.edge_low); | ||
| 667 | w.set_level_high(idx % 8, cfg.level_high); | ||
| 668 | w.set_level_low(idx % 8, cfg.level_low); | ||
| 669 | }); | ||
| 670 | DormantWake { | ||
| 671 | pin: self.pin.reborrow(), | ||
| 672 | cfg, | ||
| 673 | } | ||
| 674 | } | ||
| 642 | } | 675 | } |
| 643 | 676 | ||
| 644 | impl<'d, T: Pin> Drop for Flex<'d, T> { | 677 | impl<'d, T: Pin> Drop for Flex<'d, T> { |
| 645 | #[inline] | 678 | #[inline] |
| 646 | fn drop(&mut self) { | 679 | fn drop(&mut self) { |
| 680 | let idx = self.pin._pin() as usize; | ||
| 647 | self.pin.pad_ctrl().write(|_| {}); | 681 | self.pin.pad_ctrl().write(|_| {}); |
| 648 | self.pin.gpio().ctrl().write(|w| { | 682 | self.pin.gpio().ctrl().write(|w| { |
| 649 | w.set_funcsel(pac::io::vals::Gpio0ctrlFuncsel::NULL as _); | 683 | w.set_funcsel(pac::io::vals::Gpio0ctrlFuncsel::NULL as _); |
| 650 | }); | 684 | }); |
| 685 | self.pin.io().int_dormant_wake().inte(idx / 8).write_clear(|w| { | ||
| 686 | w.set_edge_high(idx % 8, true); | ||
| 687 | w.set_edge_low(idx % 8, true); | ||
| 688 | w.set_level_high(idx % 8, true); | ||
| 689 | w.set_level_low(idx % 8, true); | ||
| 690 | }); | ||
| 691 | } | ||
| 692 | } | ||
| 693 | |||
| 694 | pub struct DormantWake<'w, T: Pin> { | ||
| 695 | pin: PeripheralRef<'w, T>, | ||
| 696 | cfg: DormantWakeConfig, | ||
| 697 | } | ||
| 698 | |||
| 699 | impl<'w, T: Pin> Drop for DormantWake<'w, T> { | ||
| 700 | fn drop(&mut self) { | ||
| 701 | let idx = self.pin._pin() as usize; | ||
| 702 | self.pin.io().intr(idx / 8).write(|w| { | ||
| 703 | w.set_edge_high(idx % 8, self.cfg.edge_high); | ||
| 704 | w.set_edge_low(idx % 8, self.cfg.edge_low); | ||
| 705 | }); | ||
| 706 | self.pin.io().int_dormant_wake().inte(idx / 8).write_clear(|w| { | ||
| 707 | w.set_edge_high(idx % 8, true); | ||
| 708 | w.set_edge_low(idx % 8, true); | ||
| 709 | w.set_level_high(idx % 8, true); | ||
| 710 | w.set_level_low(idx % 8, true); | ||
| 711 | }); | ||
| 651 | } | 712 | } |
| 652 | } | 713 | } |
| 653 | 714 | ||
diff --git a/embassy-rp/src/lib.rs b/embassy-rp/src/lib.rs index 45156458d..49bd3533e 100644 --- a/embassy-rp/src/lib.rs +++ b/embassy-rp/src/lib.rs | |||
| @@ -183,6 +183,7 @@ embassy_hal_internal::peripherals! { | |||
| 183 | FLASH, | 183 | FLASH, |
| 184 | 184 | ||
| 185 | ADC, | 185 | ADC, |
| 186 | ADC_TEMP_SENSOR, | ||
| 186 | 187 | ||
| 187 | CORE1, | 188 | CORE1, |
| 188 | 189 | ||
diff --git a/examples/rp/src/bin/adc.rs b/examples/rp/src/bin/adc.rs index 81a8b8340..02bc493b6 100644 --- a/examples/rp/src/bin/adc.rs +++ b/examples/rp/src/bin/adc.rs | |||
| @@ -7,7 +7,7 @@ | |||
| 7 | 7 | ||
| 8 | use defmt::*; | 8 | use defmt::*; |
| 9 | use embassy_executor::Spawner; | 9 | use embassy_executor::Spawner; |
| 10 | use embassy_rp::adc::{Adc, Config, InterruptHandler, Pin}; | 10 | use embassy_rp::adc::{Adc, Channel, Config, InterruptHandler}; |
| 11 | use embassy_rp::bind_interrupts; | 11 | use embassy_rp::bind_interrupts; |
| 12 | use embassy_rp::gpio::Pull; | 12 | use embassy_rp::gpio::Pull; |
| 13 | use embassy_time::{Duration, Timer}; | 13 | use embassy_time::{Duration, Timer}; |
| @@ -22,9 +22,10 @@ async fn main(_spawner: Spawner) { | |||
| 22 | let p = embassy_rp::init(Default::default()); | 22 | let p = embassy_rp::init(Default::default()); |
| 23 | let mut adc = Adc::new(p.ADC, Irqs, Config::default()); | 23 | let mut adc = Adc::new(p.ADC, Irqs, Config::default()); |
| 24 | 24 | ||
| 25 | let mut p26 = Pin::new(p.PIN_26, Pull::None); | 25 | let mut p26 = Channel::new_pin(p.PIN_26, Pull::None); |
| 26 | let mut p27 = Pin::new(p.PIN_27, Pull::None); | 26 | let mut p27 = Channel::new_pin(p.PIN_27, Pull::None); |
| 27 | let mut p28 = Pin::new(p.PIN_28, Pull::None); | 27 | let mut p28 = Channel::new_pin(p.PIN_28, Pull::None); |
| 28 | let mut ts = Channel::new_temp_sensor(p.ADC_TEMP_SENSOR); | ||
| 28 | 29 | ||
| 29 | loop { | 30 | loop { |
| 30 | let level = adc.read(&mut p26).await.unwrap(); | 31 | let level = adc.read(&mut p26).await.unwrap(); |
| @@ -33,7 +34,7 @@ async fn main(_spawner: Spawner) { | |||
| 33 | info!("Pin 27 ADC: {}", level); | 34 | info!("Pin 27 ADC: {}", level); |
| 34 | let level = adc.read(&mut p28).await.unwrap(); | 35 | let level = adc.read(&mut p28).await.unwrap(); |
| 35 | info!("Pin 28 ADC: {}", level); | 36 | info!("Pin 28 ADC: {}", level); |
| 36 | let temp = adc.read_temperature().await.unwrap(); | 37 | let temp = adc.read(&mut ts).await.unwrap(); |
| 37 | info!("Temp: {} degrees", convert_to_celsius(temp)); | 38 | info!("Temp: {} degrees", convert_to_celsius(temp)); |
| 38 | Timer::after(Duration::from_secs(1)).await; | 39 | Timer::after(Duration::from_secs(1)).await; |
| 39 | } | 40 | } |
diff --git a/examples/std/Cargo.toml b/examples/std/Cargo.toml index 42adede10..544176828 100644 --- a/examples/std/Cargo.toml +++ b/examples/std/Cargo.toml | |||
| @@ -9,7 +9,7 @@ embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["lo | |||
| 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.2", 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-tuntap = { version = "0.1.0", path = "../../embassy-net-tuntap" } |
| 13 | embedded-io = { version = "0.4.0", features = ["async", "std", "futures"] } | 13 | embedded-io = { version = "0.4.0", features = ["async", "std", "futures"] } |
| 14 | critical-section = { version = "1.1", features = ["std"] } | 14 | critical-section = { version = "1.1", features = ["std"] } |
| 15 | 15 | ||
| @@ -18,7 +18,6 @@ env_logger = "0.9.0" | |||
| 18 | futures = { version = "0.3.17" } | 18 | futures = { version = "0.3.17" } |
| 19 | log = "0.4.14" | 19 | log = "0.4.14" |
| 20 | nix = "0.26.2" | 20 | nix = "0.26.2" |
| 21 | libc = "0.2.101" | ||
| 22 | clap = { version = "3.0.0-beta.5", features = ["derive"] } | 21 | clap = { version = "3.0.0-beta.5", features = ["derive"] } |
| 23 | rand_core = { version = "0.6.3", features = ["std"] } | 22 | rand_core = { version = "0.6.3", features = ["std"] } |
| 24 | heapless = { version = "0.7.5", default-features = false } | 23 | heapless = { version = "0.7.5", default-features = false } |
diff --git a/examples/std/src/bin/net.rs b/examples/std/src/bin/net.rs index 3aadb029d..e0de14162 100644 --- a/examples/std/src/bin/net.rs +++ b/examples/std/src/bin/net.rs | |||
| @@ -6,6 +6,7 @@ use clap::Parser; | |||
| 6 | use embassy_executor::{Executor, Spawner}; | 6 | use embassy_executor::{Executor, Spawner}; |
| 7 | use embassy_net::tcp::TcpSocket; | 7 | use embassy_net::tcp::TcpSocket; |
| 8 | use embassy_net::{Config, Ipv4Address, Ipv4Cidr, Stack, StackResources}; | 8 | use embassy_net::{Config, Ipv4Address, Ipv4Cidr, Stack, StackResources}; |
| 9 | use embassy_net_tuntap::TunTapDevice; | ||
| 9 | use embassy_time::Duration; | 10 | use embassy_time::Duration; |
| 10 | use embedded_io::asynch::Write; | 11 | use embedded_io::asynch::Write; |
| 11 | use heapless::Vec; | 12 | use heapless::Vec; |
| @@ -13,10 +14,6 @@ use log::*; | |||
| 13 | use rand_core::{OsRng, RngCore}; | 14 | use rand_core::{OsRng, RngCore}; |
| 14 | use static_cell::{make_static, StaticCell}; | 15 | use static_cell::{make_static, StaticCell}; |
| 15 | 16 | ||
| 16 | #[path = "../tuntap.rs"] | ||
| 17 | mod tuntap; | ||
| 18 | |||
| 19 | use crate::tuntap::TunTapDevice; | ||
| 20 | #[derive(Parser)] | 17 | #[derive(Parser)] |
| 21 | #[clap(version = "1.0")] | 18 | #[clap(version = "1.0")] |
| 22 | struct Opts { | 19 | struct Opts { |
diff --git a/examples/std/src/bin/net_dns.rs b/examples/std/src/bin/net_dns.rs index 65b5a2cd9..6c19874d5 100644 --- a/examples/std/src/bin/net_dns.rs +++ b/examples/std/src/bin/net_dns.rs | |||
| @@ -6,15 +6,12 @@ use clap::Parser; | |||
| 6 | use embassy_executor::{Executor, Spawner}; | 6 | use embassy_executor::{Executor, Spawner}; |
| 7 | use embassy_net::dns::DnsQueryType; | 7 | use embassy_net::dns::DnsQueryType; |
| 8 | use embassy_net::{Config, Ipv4Address, Ipv4Cidr, Stack, StackResources}; | 8 | use embassy_net::{Config, Ipv4Address, Ipv4Cidr, Stack, StackResources}; |
| 9 | use embassy_net_tuntap::TunTapDevice; | ||
| 9 | use heapless::Vec; | 10 | use heapless::Vec; |
| 10 | use log::*; | 11 | use log::*; |
| 11 | use rand_core::{OsRng, RngCore}; | 12 | use rand_core::{OsRng, RngCore}; |
| 12 | use static_cell::{make_static, StaticCell}; | 13 | use static_cell::{make_static, StaticCell}; |
| 13 | 14 | ||
| 14 | #[path = "../tuntap.rs"] | ||
| 15 | mod tuntap; | ||
| 16 | |||
| 17 | use crate::tuntap::TunTapDevice; | ||
| 18 | #[derive(Parser)] | 15 | #[derive(Parser)] |
| 19 | #[clap(version = "1.0")] | 16 | #[clap(version = "1.0")] |
| 20 | struct Opts { | 17 | struct Opts { |
diff --git a/examples/std/src/bin/net_udp.rs b/examples/std/src/bin/net_udp.rs index 3fc46156c..98dcc9925 100644 --- a/examples/std/src/bin/net_udp.rs +++ b/examples/std/src/bin/net_udp.rs | |||
| @@ -4,15 +4,12 @@ use clap::Parser; | |||
| 4 | use embassy_executor::{Executor, Spawner}; | 4 | use embassy_executor::{Executor, Spawner}; |
| 5 | use embassy_net::udp::{PacketMetadata, UdpSocket}; | 5 | use embassy_net::udp::{PacketMetadata, UdpSocket}; |
| 6 | use embassy_net::{Config, Ipv4Address, Ipv4Cidr, Stack, StackResources}; | 6 | use embassy_net::{Config, Ipv4Address, Ipv4Cidr, Stack, StackResources}; |
| 7 | use embassy_net_tuntap::TunTapDevice; | ||
| 7 | use heapless::Vec; | 8 | use heapless::Vec; |
| 8 | use log::*; | 9 | use log::*; |
| 9 | use rand_core::{OsRng, RngCore}; | 10 | use rand_core::{OsRng, RngCore}; |
| 10 | use static_cell::{make_static, StaticCell}; | 11 | use static_cell::{make_static, StaticCell}; |
| 11 | 12 | ||
| 12 | #[path = "../tuntap.rs"] | ||
| 13 | mod tuntap; | ||
| 14 | |||
| 15 | use crate::tuntap::TunTapDevice; | ||
| 16 | #[derive(Parser)] | 13 | #[derive(Parser)] |
| 17 | #[clap(version = "1.0")] | 14 | #[clap(version = "1.0")] |
| 18 | struct Opts { | 15 | struct Opts { |
diff --git a/examples/std/src/bin/tcp_accept.rs b/examples/std/src/bin/tcp_accept.rs index df09986ac..0c920a3fb 100644 --- a/examples/std/src/bin/tcp_accept.rs +++ b/examples/std/src/bin/tcp_accept.rs | |||
| @@ -7,6 +7,7 @@ use clap::Parser; | |||
| 7 | use embassy_executor::{Executor, Spawner}; | 7 | use embassy_executor::{Executor, Spawner}; |
| 8 | use embassy_net::tcp::TcpSocket; | 8 | use embassy_net::tcp::TcpSocket; |
| 9 | use embassy_net::{Config, Ipv4Address, Ipv4Cidr, Stack, StackResources}; | 9 | use embassy_net::{Config, Ipv4Address, Ipv4Cidr, Stack, StackResources}; |
| 10 | use embassy_net_tuntap::TunTapDevice; | ||
| 10 | use embassy_time::{Duration, Timer}; | 11 | use embassy_time::{Duration, Timer}; |
| 11 | use embedded_io::asynch::Write as _; | 12 | use embedded_io::asynch::Write as _; |
| 12 | use heapless::Vec; | 13 | use heapless::Vec; |
| @@ -14,10 +15,6 @@ use log::*; | |||
| 14 | use rand_core::{OsRng, RngCore}; | 15 | use rand_core::{OsRng, RngCore}; |
| 15 | use static_cell::{make_static, StaticCell}; | 16 | use static_cell::{make_static, StaticCell}; |
| 16 | 17 | ||
| 17 | #[path = "../tuntap.rs"] | ||
| 18 | mod tuntap; | ||
| 19 | |||
| 20 | use crate::tuntap::TunTapDevice; | ||
| 21 | #[derive(Parser)] | 18 | #[derive(Parser)] |
| 22 | #[clap(version = "1.0")] | 19 | #[clap(version = "1.0")] |
| 23 | struct Opts { | 20 | struct Opts { |
diff --git a/tests/rp/src/bin/adc.rs b/tests/rp/src/bin/adc.rs index e659844ae..d6d58f0c0 100644 --- a/tests/rp/src/bin/adc.rs +++ b/tests/rp/src/bin/adc.rs | |||
| @@ -6,7 +6,7 @@ mod common; | |||
| 6 | 6 | ||
| 7 | use defmt::*; | 7 | use defmt::*; |
| 8 | use embassy_executor::Spawner; | 8 | use embassy_executor::Spawner; |
| 9 | use embassy_rp::adc::{Adc, Config, InterruptHandler, Pin}; | 9 | use embassy_rp::adc::{Adc, Channel, Config, InterruptHandler, Sample}; |
| 10 | use embassy_rp::bind_interrupts; | 10 | use embassy_rp::bind_interrupts; |
| 11 | use embassy_rp::gpio::Pull; | 11 | use embassy_rp::gpio::Pull; |
| 12 | use {defmt_rtt as _, panic_probe as _}; | 12 | use {defmt_rtt as _, panic_probe as _}; |
| @@ -22,12 +22,12 @@ async fn main(_spawner: Spawner) { | |||
| 22 | 22 | ||
| 23 | { | 23 | { |
| 24 | { | 24 | { |
| 25 | let mut p = Pin::new(&mut p.PIN_26, Pull::Down); | 25 | let mut p = Channel::new_pin(&mut p.PIN_26, Pull::Down); |
| 26 | defmt::assert!(adc.blocking_read(&mut p).unwrap() < 0b01_0000_0000); | 26 | defmt::assert!(adc.blocking_read(&mut p).unwrap() < 0b01_0000_0000); |
| 27 | defmt::assert!(adc.read(&mut p).await.unwrap() < 0b01_0000_0000); | 27 | defmt::assert!(adc.read(&mut p).await.unwrap() < 0b01_0000_0000); |
| 28 | } | 28 | } |
| 29 | { | 29 | { |
| 30 | let mut p = Pin::new(&mut p.PIN_26, Pull::Up); | 30 | let mut p = Channel::new_pin(&mut p.PIN_26, Pull::Up); |
| 31 | defmt::assert!(adc.blocking_read(&mut p).unwrap() > 0b11_0000_0000); | 31 | defmt::assert!(adc.blocking_read(&mut p).unwrap() > 0b11_0000_0000); |
| 32 | defmt::assert!(adc.read(&mut p).await.unwrap() > 0b11_0000_0000); | 32 | defmt::assert!(adc.read(&mut p).await.unwrap() > 0b11_0000_0000); |
| 33 | } | 33 | } |
| @@ -35,21 +35,21 @@ async fn main(_spawner: Spawner) { | |||
| 35 | // not bothering with async reads from now on | 35 | // not bothering with async reads from now on |
| 36 | { | 36 | { |
| 37 | { | 37 | { |
| 38 | let mut p = Pin::new(&mut p.PIN_27, Pull::Down); | 38 | let mut p = Channel::new_pin(&mut p.PIN_27, Pull::Down); |
| 39 | defmt::assert!(adc.blocking_read(&mut p).unwrap() < 0b01_0000_0000); | 39 | defmt::assert!(adc.blocking_read(&mut p).unwrap() < 0b01_0000_0000); |
| 40 | } | 40 | } |
| 41 | { | 41 | { |
| 42 | let mut p = Pin::new(&mut p.PIN_27, Pull::Up); | 42 | let mut p = Channel::new_pin(&mut p.PIN_27, Pull::Up); |
| 43 | defmt::assert!(adc.blocking_read(&mut p).unwrap() > 0b11_0000_0000); | 43 | defmt::assert!(adc.blocking_read(&mut p).unwrap() > 0b11_0000_0000); |
| 44 | } | 44 | } |
| 45 | } | 45 | } |
| 46 | { | 46 | { |
| 47 | { | 47 | { |
| 48 | let mut p = Pin::new(&mut p.PIN_28, Pull::Down); | 48 | let mut p = Channel::new_pin(&mut p.PIN_28, Pull::Down); |
| 49 | defmt::assert!(adc.blocking_read(&mut p).unwrap() < 0b01_0000_0000); | 49 | defmt::assert!(adc.blocking_read(&mut p).unwrap() < 0b01_0000_0000); |
| 50 | } | 50 | } |
| 51 | { | 51 | { |
| 52 | let mut p = Pin::new(&mut p.PIN_28, Pull::Up); | 52 | let mut p = Channel::new_pin(&mut p.PIN_28, Pull::Up); |
| 53 | defmt::assert!(adc.blocking_read(&mut p).unwrap() > 0b11_0000_0000); | 53 | defmt::assert!(adc.blocking_read(&mut p).unwrap() > 0b11_0000_0000); |
| 54 | } | 54 | } |
| 55 | } | 55 | } |
| @@ -57,24 +57,71 @@ async fn main(_spawner: Spawner) { | |||
| 57 | // gp29 is connected to vsys through a 200k/100k divider, | 57 | // gp29 is connected to vsys through a 200k/100k divider, |
| 58 | // adding pulls should change the value | 58 | // adding pulls should change the value |
| 59 | let low = { | 59 | let low = { |
| 60 | let mut p = Pin::new(&mut p.PIN_29, Pull::Down); | 60 | let mut p = Channel::new_pin(&mut p.PIN_29, Pull::Down); |
| 61 | adc.blocking_read(&mut p).unwrap() | 61 | adc.blocking_read(&mut p).unwrap() |
| 62 | }; | 62 | }; |
| 63 | let none = { | 63 | let none = { |
| 64 | let mut p = Pin::new(&mut p.PIN_29, Pull::None); | 64 | let mut p = Channel::new_pin(&mut p.PIN_29, Pull::None); |
| 65 | adc.blocking_read(&mut p).unwrap() | 65 | adc.blocking_read(&mut p).unwrap() |
| 66 | }; | 66 | }; |
| 67 | let up = { | 67 | let up = { |
| 68 | let mut p = Pin::new(&mut p.PIN_29, Pull::Up); | 68 | let mut p = Channel::new_pin(&mut p.PIN_29, Pull::Up); |
| 69 | adc.blocking_read(&mut p).unwrap() | 69 | adc.blocking_read(&mut p).unwrap() |
| 70 | }; | 70 | }; |
| 71 | defmt::assert!(low < none); | 71 | defmt::assert!(low < none); |
| 72 | defmt::assert!(none < up); | 72 | defmt::assert!(none < up); |
| 73 | } | 73 | } |
| 74 | { | ||
| 75 | let temp = convert_to_celsius( | ||
| 76 | adc.read(&mut Channel::new_temp_sensor(&mut p.ADC_TEMP_SENSOR)) | ||
| 77 | .await | ||
| 78 | .unwrap(), | ||
| 79 | ); | ||
| 80 | defmt::assert!(temp > 0.0); | ||
| 81 | defmt::assert!(temp < 60.0); | ||
| 82 | } | ||
| 74 | 83 | ||
| 75 | let temp = convert_to_celsius(adc.read_temperature().await.unwrap()); | 84 | // run a bunch of conversions. we'll only check gp29 and the temp |
| 76 | defmt::assert!(temp > 0.0); | 85 | // sensor here for brevity, if those two work the rest will too. |
| 77 | defmt::assert!(temp < 60.0); | 86 | { |
| 87 | // gp29 is connected to vsys through a 200k/100k divider, | ||
| 88 | // adding pulls should change the value | ||
| 89 | let mut low = [0u16; 16]; | ||
| 90 | let mut none = [0u8; 16]; | ||
| 91 | let mut up = [Sample::default(); 16]; | ||
| 92 | adc.read_many( | ||
| 93 | &mut Channel::new_pin(&mut p.PIN_29, Pull::Down), | ||
| 94 | &mut low, | ||
| 95 | &mut p.DMA_CH0, | ||
| 96 | ) | ||
| 97 | .await | ||
| 98 | .unwrap(); | ||
| 99 | adc.read_many( | ||
| 100 | &mut Channel::new_pin(&mut p.PIN_29, Pull::None), | ||
| 101 | &mut none, | ||
| 102 | &mut p.DMA_CH0, | ||
| 103 | ) | ||
| 104 | .await | ||
| 105 | .unwrap(); | ||
| 106 | adc.read_many_raw(&mut Channel::new_pin(&mut p.PIN_29, Pull::Up), &mut up, &mut p.DMA_CH0) | ||
| 107 | .await; | ||
| 108 | defmt::assert!(low.iter().zip(none.iter()).all(|(l, n)| *l >> 4 < *n as u16)); | ||
| 109 | defmt::assert!(up.iter().all(|s| s.good())); | ||
| 110 | defmt::assert!(none.iter().zip(up.iter()).all(|(n, u)| (*n as u16) < u.value())); | ||
| 111 | } | ||
| 112 | { | ||
| 113 | let mut temp = [0u16; 16]; | ||
| 114 | adc.read_many( | ||
| 115 | &mut Channel::new_temp_sensor(&mut p.ADC_TEMP_SENSOR), | ||
| 116 | &mut temp, | ||
| 117 | &mut p.DMA_CH0, | ||
| 118 | ) | ||
| 119 | .await | ||
| 120 | .unwrap(); | ||
| 121 | let temp = temp.map(convert_to_celsius); | ||
| 122 | defmt::assert!(temp.iter().all(|t| *t > 0.0)); | ||
| 123 | defmt::assert!(temp.iter().all(|t| *t < 60.0)); | ||
| 124 | } | ||
| 78 | 125 | ||
| 79 | info!("Test OK"); | 126 | info!("Test OK"); |
| 80 | cortex_m::asm::bkpt(); | 127 | cortex_m::asm::bkpt(); |
