From b166ed6b78db0737005a65c1e444ce7563de7da3 Mon Sep 17 00:00:00 2001 From: pennae Date: Fri, 21 Jul 2023 21:31:44 +0200 Subject: rp: generalize adc inputs from pins to channels this lets us treat pins and the temperature sensor uniformly using the same interface. uniformity in turn lets us add more adc features without combinatorial explosion of methods and types needed to handle them all. --- examples/rp/src/bin/adc.rs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'examples') diff --git a/examples/rp/src/bin/adc.rs b/examples/rp/src/bin/adc.rs index 81a8b8340..c58695512 100644 --- a/examples/rp/src/bin/adc.rs +++ b/examples/rp/src/bin/adc.rs @@ -7,7 +7,7 @@ use defmt::*; use embassy_executor::Spawner; -use embassy_rp::adc::{Adc, Config, InterruptHandler, Pin}; +use embassy_rp::adc::{Adc, Channel, Config, InterruptHandler}; use embassy_rp::bind_interrupts; use embassy_rp::gpio::Pull; use embassy_time::{Duration, Timer}; @@ -22,9 +22,10 @@ async fn main(_spawner: Spawner) { let p = embassy_rp::init(Default::default()); let mut adc = Adc::new(p.ADC, Irqs, Config::default()); - let mut p26 = Pin::new(p.PIN_26, Pull::None); - let mut p27 = Pin::new(p.PIN_27, Pull::None); - let mut p28 = Pin::new(p.PIN_28, Pull::None); + let mut p26 = Channel::new_pin(p.PIN_26, Pull::None); + let mut p27 = Channel::new_pin(p.PIN_27, Pull::None); + let mut p28 = Channel::new_pin(p.PIN_28, Pull::None); + let mut ts = Channel::new_sensor(p.ADC_TEMP_SENSOR); loop { let level = adc.read(&mut p26).await.unwrap(); @@ -33,7 +34,7 @@ async fn main(_spawner: Spawner) { info!("Pin 27 ADC: {}", level); let level = adc.read(&mut p28).await.unwrap(); info!("Pin 28 ADC: {}", level); - let temp = adc.read_temperature().await.unwrap(); + let temp = adc.read(&mut ts).await.unwrap(); info!("Temp: {} degrees", convert_to_celsius(temp)); Timer::after(Duration::from_secs(1)).await; } -- cgit From a6b8f3d99478266b4f110e9c150ce3add5c3ffc6 Mon Sep 17 00:00:00 2001 From: pennae Date: Fri, 21 Jul 2023 23:34:12 +0200 Subject: rp: add single-channel dma from adc with uniform treatment of adc inputs it's easy enough to add a new sampling method. dma sampling only supports one channel at the moment, though round-robin sampling would be a simple extension (probably a new trait that's implemented for Channel and &[Channel]). continuous dma as proposed in #1608 also isn't done here, we'd expect that to be a compound dma::Channel that internally splits a buffer in half and dispatches callbacks or something like that. --- examples/rp/src/bin/adc.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'examples') diff --git a/examples/rp/src/bin/adc.rs b/examples/rp/src/bin/adc.rs index c58695512..02bc493b6 100644 --- a/examples/rp/src/bin/adc.rs +++ b/examples/rp/src/bin/adc.rs @@ -25,7 +25,7 @@ async fn main(_spawner: Spawner) { let mut p26 = Channel::new_pin(p.PIN_26, Pull::None); let mut p27 = Channel::new_pin(p.PIN_27, Pull::None); let mut p28 = Channel::new_pin(p.PIN_28, Pull::None); - let mut ts = Channel::new_sensor(p.ADC_TEMP_SENSOR); + let mut ts = Channel::new_temp_sensor(p.ADC_TEMP_SENSOR); loop { let level = adc.read(&mut p26).await.unwrap(); -- cgit From 4d60c715e683aaadf25d9f066bde805c725fefb4 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Thu, 3 Aug 2023 14:23:11 +0200 Subject: net: move tuntap from std example to separate crate. (#1737) --- examples/std/Cargo.toml | 3 +- examples/std/src/bin/net.rs | 5 +- examples/std/src/bin/net_dns.rs | 5 +- examples/std/src/bin/net_udp.rs | 5 +- examples/std/src/bin/tcp_accept.rs | 5 +- examples/std/src/tuntap.rs | 224 ------------------------------------- 6 files changed, 5 insertions(+), 242 deletions(-) delete mode 100644 examples/std/src/tuntap.rs (limited to 'examples') 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 embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["arch-std", "executor-thread", "log", "nightly", "integrated-timers"] } embassy-time = { version = "0.1.2", path = "../../embassy-time", features = ["log", "std", "nightly"] } embassy-net = { version = "0.1.0", path = "../../embassy-net", features=[ "std", "nightly", "log", "medium-ethernet", "tcp", "udp", "dns", "dhcpv4", "unstable-traits", "proto-ipv6"] } -embassy-net-driver = { version = "0.1.0", path = "../../embassy-net-driver" } +embassy-net-tuntap = { version = "0.1.0", path = "../../embassy-net-tuntap" } embedded-io = { version = "0.4.0", features = ["async", "std", "futures"] } critical-section = { version = "1.1", features = ["std"] } @@ -18,7 +18,6 @@ env_logger = "0.9.0" futures = { version = "0.3.17" } log = "0.4.14" nix = "0.26.2" -libc = "0.2.101" clap = { version = "3.0.0-beta.5", features = ["derive"] } rand_core = { version = "0.6.3", features = ["std"] } 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; use embassy_executor::{Executor, Spawner}; use embassy_net::tcp::TcpSocket; use embassy_net::{Config, Ipv4Address, Ipv4Cidr, Stack, StackResources}; +use embassy_net_tuntap::TunTapDevice; use embassy_time::Duration; use embedded_io::asynch::Write; use heapless::Vec; @@ -13,10 +14,6 @@ use log::*; use rand_core::{OsRng, RngCore}; use static_cell::{make_static, StaticCell}; -#[path = "../tuntap.rs"] -mod tuntap; - -use crate::tuntap::TunTapDevice; #[derive(Parser)] #[clap(version = "1.0")] 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; use embassy_executor::{Executor, Spawner}; use embassy_net::dns::DnsQueryType; use embassy_net::{Config, Ipv4Address, Ipv4Cidr, Stack, StackResources}; +use embassy_net_tuntap::TunTapDevice; use heapless::Vec; use log::*; use rand_core::{OsRng, RngCore}; use static_cell::{make_static, StaticCell}; -#[path = "../tuntap.rs"] -mod tuntap; - -use crate::tuntap::TunTapDevice; #[derive(Parser)] #[clap(version = "1.0")] 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; use embassy_executor::{Executor, Spawner}; use embassy_net::udp::{PacketMetadata, UdpSocket}; use embassy_net::{Config, Ipv4Address, Ipv4Cidr, Stack, StackResources}; +use embassy_net_tuntap::TunTapDevice; use heapless::Vec; use log::*; use rand_core::{OsRng, RngCore}; use static_cell::{make_static, StaticCell}; -#[path = "../tuntap.rs"] -mod tuntap; - -use crate::tuntap::TunTapDevice; #[derive(Parser)] #[clap(version = "1.0")] 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; use embassy_executor::{Executor, Spawner}; use embassy_net::tcp::TcpSocket; use embassy_net::{Config, Ipv4Address, Ipv4Cidr, Stack, StackResources}; +use embassy_net_tuntap::TunTapDevice; use embassy_time::{Duration, Timer}; use embedded_io::asynch::Write as _; use heapless::Vec; @@ -14,10 +15,6 @@ use log::*; use rand_core::{OsRng, RngCore}; use static_cell::{make_static, StaticCell}; -#[path = "../tuntap.rs"] -mod tuntap; - -use crate::tuntap::TunTapDevice; #[derive(Parser)] #[clap(version = "1.0")] struct Opts { diff --git a/examples/std/src/tuntap.rs b/examples/std/src/tuntap.rs deleted file mode 100644 index 167c3da5f..000000000 --- a/examples/std/src/tuntap.rs +++ /dev/null @@ -1,224 +0,0 @@ -use std::io; -use std::io::{Read, Write}; -use std::os::unix::io::{AsRawFd, RawFd}; -use std::task::Context; - -use async_io::Async; -use embassy_net_driver::{self, Capabilities, Driver, HardwareAddress, LinkState}; -use log::*; - -pub const SIOCGIFMTU: libc::c_ulong = 0x8921; -pub const _SIOCGIFINDEX: libc::c_ulong = 0x8933; -pub const _ETH_P_ALL: libc::c_short = 0x0003; -pub const TUNSETIFF: libc::c_ulong = 0x400454CA; -pub const _IFF_TUN: libc::c_int = 0x0001; -pub const IFF_TAP: libc::c_int = 0x0002; -pub const IFF_NO_PI: libc::c_int = 0x1000; - -const ETHERNET_HEADER_LEN: usize = 14; - -#[repr(C)] -#[derive(Debug)] -struct ifreq { - ifr_name: [libc::c_char; libc::IF_NAMESIZE], - ifr_data: libc::c_int, /* ifr_ifindex or ifr_mtu */ -} - -fn ifreq_for(name: &str) -> ifreq { - let mut ifreq = ifreq { - ifr_name: [0; libc::IF_NAMESIZE], - ifr_data: 0, - }; - for (i, byte) in name.as_bytes().iter().enumerate() { - ifreq.ifr_name[i] = *byte as libc::c_char - } - ifreq -} - -fn ifreq_ioctl(lower: libc::c_int, ifreq: &mut ifreq, cmd: libc::c_ulong) -> io::Result { - unsafe { - let res = libc::ioctl(lower, cmd as _, ifreq as *mut ifreq); - if res == -1 { - return Err(io::Error::last_os_error()); - } - } - - Ok(ifreq.ifr_data) -} - -#[derive(Debug)] -pub struct TunTap { - fd: libc::c_int, - mtu: usize, -} - -impl AsRawFd for TunTap { - fn as_raw_fd(&self) -> RawFd { - self.fd - } -} - -impl TunTap { - pub fn new(name: &str) -> io::Result { - unsafe { - let fd = libc::open( - "/dev/net/tun\0".as_ptr() as *const libc::c_char, - libc::O_RDWR | libc::O_NONBLOCK, - ); - if fd == -1 { - return Err(io::Error::last_os_error()); - } - - let mut ifreq = ifreq_for(name); - ifreq.ifr_data = IFF_TAP | IFF_NO_PI; - ifreq_ioctl(fd, &mut ifreq, TUNSETIFF)?; - - let socket = libc::socket(libc::AF_INET, libc::SOCK_DGRAM, libc::IPPROTO_IP); - if socket == -1 { - return Err(io::Error::last_os_error()); - } - - let ip_mtu = ifreq_ioctl(socket, &mut ifreq, SIOCGIFMTU); - libc::close(socket); - let ip_mtu = ip_mtu? as usize; - - // SIOCGIFMTU returns the IP MTU (typically 1500 bytes.) - // smoltcp counts the entire Ethernet packet in the MTU, so add the Ethernet header size to it. - let mtu = ip_mtu + ETHERNET_HEADER_LEN; - - Ok(TunTap { fd, mtu }) - } - } -} - -impl Drop for TunTap { - fn drop(&mut self) { - unsafe { - libc::close(self.fd); - } - } -} - -impl io::Read for TunTap { - fn read(&mut self, buf: &mut [u8]) -> io::Result { - let len = unsafe { libc::read(self.fd, buf.as_mut_ptr() as *mut libc::c_void, buf.len()) }; - if len == -1 { - Err(io::Error::last_os_error()) - } else { - Ok(len as usize) - } - } -} - -impl io::Write for TunTap { - fn write(&mut self, buf: &[u8]) -> io::Result { - let len = unsafe { libc::write(self.fd, buf.as_ptr() as *mut libc::c_void, buf.len()) }; - if len == -1 { - Err(io::Error::last_os_error()) - } else { - Ok(len as usize) - } - } - - fn flush(&mut self) -> io::Result<()> { - Ok(()) - } -} - -pub struct TunTapDevice { - device: Async, -} - -impl TunTapDevice { - pub fn new(name: &str) -> io::Result { - Ok(Self { - device: Async::new(TunTap::new(name)?)?, - }) - } -} - -impl Driver for TunTapDevice { - type RxToken<'a> = RxToken where Self: 'a; - type TxToken<'a> = TxToken<'a> where Self: 'a; - - fn receive(&mut self, cx: &mut Context) -> Option<(Self::RxToken<'_>, Self::TxToken<'_>)> { - let mut buf = vec![0; self.device.get_ref().mtu]; - loop { - match self.device.get_mut().read(&mut buf) { - Ok(n) => { - buf.truncate(n); - return Some(( - RxToken { buffer: buf }, - TxToken { - device: &mut self.device, - }, - )); - } - Err(e) if e.kind() == io::ErrorKind::WouldBlock => { - if !self.device.poll_readable(cx).is_ready() { - return None; - } - } - Err(e) => panic!("read error: {:?}", e), - } - } - } - - fn transmit(&mut self, _cx: &mut Context) -> Option> { - Some(TxToken { - device: &mut self.device, - }) - } - - fn capabilities(&self) -> Capabilities { - let mut caps = Capabilities::default(); - caps.max_transmission_unit = self.device.get_ref().mtu; - caps - } - - fn link_state(&mut self, _cx: &mut Context) -> LinkState { - LinkState::Up - } - - fn hardware_address(&self) -> HardwareAddress { - HardwareAddress::Ethernet([0x02, 0x03, 0x04, 0x05, 0x06, 0x07]) - } -} - -#[doc(hidden)] -pub struct RxToken { - buffer: Vec, -} - -impl embassy_net_driver::RxToken for RxToken { - fn consume(mut self, f: F) -> R - where - F: FnOnce(&mut [u8]) -> R, - { - f(&mut self.buffer) - } -} - -#[doc(hidden)] -pub struct TxToken<'a> { - device: &'a mut Async, -} - -impl<'a> embassy_net_driver::TxToken for TxToken<'a> { - fn consume(self, len: usize, f: F) -> R - where - F: FnOnce(&mut [u8]) -> R, - { - let mut buffer = vec![0; len]; - let result = f(&mut buffer); - - // todo handle WouldBlock with async - match self.device.get_mut().write(&buffer) { - Ok(_) => {} - Err(e) if e.kind() == io::ErrorKind::WouldBlock => info!("transmit WouldBlock"), - Err(e) => panic!("transmit error: {:?}", e), - } - - result - } -} -- cgit