forked from esp-rs/esp-hal
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Async WiFi with embassy - Add embassy_net::Driver impl for WifiDevice - Add embassy_dhcp example - Update README with embassy_dhcp running instruction Notes: TCP connection may fail a few times until the esp gets an IP address, it seems there is no way to await dhcp completion in embassy_net yet. * Put embassy-net behind feature - Whilst other embassy crates can be used behind the async feature, embassy-net should be put behind its own feature * wait for dhcp to complete in example * fmt * Simplify embedded-io import * Update README, use new bleps
- Loading branch information
Showing
3 changed files
with
348 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,219 @@ | ||
#![no_std] | ||
#![no_main] | ||
#![feature(c_variadic)] | ||
#![feature(const_mut_refs)] | ||
#![feature(type_alias_impl_trait)] | ||
|
||
use embassy_executor::_export::StaticCell; | ||
use embassy_net::tcp::TcpSocket; | ||
use embassy_net::{Config, Ipv4Address, Stack, StackResources}; | ||
#[cfg(feature = "esp32")] | ||
use esp32_hal as hal; | ||
#[cfg(feature = "esp32c2")] | ||
use esp32c2_hal as hal; | ||
#[cfg(feature = "esp32c3")] | ||
use esp32c3_hal as hal; | ||
#[cfg(feature = "esp32s2")] | ||
use esp32s2_hal as hal; | ||
#[cfg(feature = "esp32s3")] | ||
use esp32s3_hal as hal; | ||
|
||
use embassy_executor::Executor; | ||
use embassy_time::{Duration, Timer}; | ||
use embedded_svc::wifi::{AccessPointInfo, ClientConfiguration, Configuration, Wifi}; | ||
use esp_backtrace as _; | ||
use esp_println::logger::init_logger; | ||
use esp_println::println; | ||
use esp_wifi::initialize; | ||
use esp_wifi::wifi::{WifiDevice, WifiError}; | ||
use hal::clock::{ClockControl, CpuClock}; | ||
use hal::Rng; | ||
use hal::{embassy, peripherals::Peripherals, prelude::*, timer::TimerGroup, Rtc}; | ||
|
||
#[cfg(any(feature = "esp32c3", feature = "esp32c2"))] | ||
use hal::system::SystemExt; | ||
|
||
#[cfg(any(feature = "esp32c3", feature = "esp32c2"))] | ||
use riscv_rt::entry; | ||
#[cfg(any(feature = "esp32", feature = "esp32s3", feature = "esp32s2"))] | ||
use xtensa_lx_rt::entry; | ||
|
||
const SSID: &str = env!("SSID"); | ||
const PASSWORD: &str = env!("PASSWORD"); | ||
|
||
macro_rules! singleton { | ||
($val:expr) => {{ | ||
type T = impl Sized; | ||
static STATIC_CELL: StaticCell<T> = StaticCell::new(); | ||
let (x,) = STATIC_CELL.init(($val,)); | ||
x | ||
}}; | ||
} | ||
|
||
static EXECUTOR: StaticCell<Executor> = StaticCell::new(); | ||
|
||
#[entry] | ||
fn main() -> ! { | ||
init_logger(log::LevelFilter::Info); | ||
esp_wifi::init_heap(); | ||
|
||
let peripherals = Peripherals::take(); | ||
|
||
#[cfg(not(feature = "esp32"))] | ||
let system = peripherals.SYSTEM.split(); | ||
#[cfg(feature = "esp32")] | ||
let system = peripherals.DPORT.split(); | ||
|
||
#[cfg(feature = "esp32c3")] | ||
let clocks = ClockControl::configure(system.clock_control, CpuClock::Clock160MHz).freeze(); | ||
#[cfg(feature = "esp32c2")] | ||
let clocks = ClockControl::configure(system.clock_control, CpuClock::Clock120MHz).freeze(); | ||
#[cfg(any(feature = "esp32", feature = "esp32s3", feature = "esp32s2"))] | ||
let clocks = ClockControl::configure(system.clock_control, CpuClock::Clock240MHz).freeze(); | ||
|
||
let mut rtc = Rtc::new(peripherals.RTC_CNTL); | ||
|
||
// Disable watchdog timers | ||
#[cfg(not(any(feature = "esp32", feature = "esp32s2")))] | ||
rtc.swd.disable(); | ||
|
||
rtc.rwdt.disable(); | ||
|
||
#[cfg(any(feature = "esp32c3", feature = "esp32c2"))] | ||
{ | ||
use hal::systimer::SystemTimer; | ||
let syst = SystemTimer::new(peripherals.SYSTIMER); | ||
initialize(syst.alarm0, Rng::new(peripherals.RNG), &clocks).unwrap(); | ||
} | ||
#[cfg(any(feature = "esp32", feature = "esp32s3", feature = "esp32s2"))] | ||
{ | ||
use hal::timer::TimerGroup; | ||
let timg1 = TimerGroup::new(peripherals.TIMG1, &clocks); | ||
initialize(timg1.timer0, Rng::new(peripherals.RNG), &clocks).unwrap(); | ||
} | ||
|
||
let mut wifi_interface = WifiDevice::new(); | ||
|
||
println!("is wifi started: {:?}", wifi_interface.is_started()); | ||
|
||
println!("Start Wifi Scan"); | ||
let res: Result<(heapless::Vec<AccessPointInfo, 10>, usize), WifiError> = | ||
wifi_interface.scan_n(); | ||
if let Ok((res, _count)) = res { | ||
for ap in res { | ||
println!("{:?}", ap); | ||
} | ||
} | ||
|
||
println!("Call wifi_connect"); | ||
let client_config = Configuration::Client(ClientConfiguration { | ||
ssid: SSID.into(), | ||
password: PASSWORD.into(), | ||
..Default::default() | ||
}); | ||
let res = wifi_interface.set_configuration(&client_config); | ||
println!("wifi_set_configuration returned {:?}", res); | ||
|
||
println!("{:?}", wifi_interface.get_capabilities()); | ||
println!("wifi_connect {:?}", wifi_interface.connect()); | ||
|
||
// wait to get connected | ||
println!("Wait to get connected"); | ||
loop { | ||
let res = wifi_interface.is_connected(); | ||
match res { | ||
Ok(connected) => { | ||
if connected { | ||
break; | ||
} | ||
} | ||
Err(err) => { | ||
println!("{:?}", err); | ||
loop {} | ||
} | ||
} | ||
} | ||
println!("{:?}", wifi_interface.is_connected()); | ||
|
||
let timer_group0 = TimerGroup::new(peripherals.TIMG0, &clocks); | ||
embassy::init(&clocks, timer_group0.timer0); | ||
|
||
let config = Config::Dhcp(Default::default()); | ||
|
||
let seed = 1234; // very random, very secure seed | ||
|
||
// Init network stack | ||
let stack = &*singleton!(Stack::new( | ||
wifi_interface, | ||
config, | ||
singleton!(StackResources::<3>::new()), | ||
seed | ||
)); | ||
|
||
let executor = EXECUTOR.init(Executor::new()); | ||
executor.run(|spawner| { | ||
spawner.spawn(net_task(&stack)).ok(); | ||
spawner.spawn(task(&stack)).ok(); | ||
}); | ||
} | ||
|
||
#[embassy_executor::task] | ||
async fn net_task(stack: &'static Stack<WifiDevice>) { | ||
stack.run().await | ||
} | ||
|
||
#[embassy_executor::task] | ||
async fn task(stack: &'static Stack<WifiDevice>) { | ||
let mut rx_buffer = [0; 4096]; | ||
let mut tx_buffer = [0; 4096]; | ||
|
||
println!("Waiting to get IP address..."); | ||
loop { | ||
if let Some(config) = stack.config() { | ||
println!("Got IP: {}", config.address); | ||
break; | ||
} | ||
Timer::after(Duration::from_millis(500)).await; | ||
} | ||
|
||
loop { | ||
Timer::after(Duration::from_millis(1_000)).await; | ||
|
||
let mut socket = TcpSocket::new(&stack, &mut rx_buffer, &mut tx_buffer); | ||
|
||
socket.set_timeout(Some(embassy_net::SmolDuration::from_secs(10))); | ||
|
||
let remote_endpoint = (Ipv4Address::new(142, 250, 185, 115), 80); | ||
println!("connecting..."); | ||
let r = socket.connect(remote_endpoint).await; | ||
if let Err(e) = r { | ||
println!("connect error: {:?}", e); | ||
continue; | ||
} | ||
println!("connected!"); | ||
let mut buf = [0; 1024]; | ||
loop { | ||
use embedded_io::asynch::Write; | ||
let r = socket | ||
.write_all(b"GET / HTTP/1.0\r\nHost: www.mobile-j.de\r\n\r\n") | ||
.await; | ||
if let Err(e) = r { | ||
println!("write error: {:?}", e); | ||
break; | ||
} | ||
let n = match socket.read(&mut buf).await { | ||
Ok(0) => { | ||
println!("read EOF"); | ||
break; | ||
} | ||
Ok(n) => n, | ||
Err(e) => { | ||
println!("read error: {:?}", e); | ||
break; | ||
} | ||
}; | ||
println!("{}", core::str::from_utf8(&buf[..n]).unwrap()); | ||
} | ||
Timer::after(Duration::from_millis(1000)).await; | ||
} | ||
} |
Oops, something went wrong.