Connect to wireless network
This commit is contained in:
parent
fc1105fdc3
commit
95ad37bcaa
3 changed files with 239 additions and 171 deletions
109
src/main.rs
109
src/main.rs
|
|
@ -1,11 +1,16 @@
|
|||
#![feature(impl_trait_in_assoc_type)]
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
extern crate panic_halt;
|
||||
|
||||
use cyw43::JoinOptions;
|
||||
use cyw43_pio::PioSpi;
|
||||
use embassy_executor::Spawner;
|
||||
use embassy_net::{Config, DhcpConfig, StackResources};
|
||||
use embassy_rp::{
|
||||
bind_interrupts,
|
||||
clocks::RoscRng,
|
||||
gpio::{Level, Output},
|
||||
peripherals::{DMA_CH0, PIO0, USB},
|
||||
pio::{self, Pio},
|
||||
|
|
@ -13,41 +18,51 @@ use embassy_rp::{
|
|||
};
|
||||
use embassy_time::Timer;
|
||||
use log::info;
|
||||
use rand::RngCore;
|
||||
use static_cell::StaticCell;
|
||||
|
||||
const WIFI_CREDENTIALS: &[(&str, &str)] =
|
||||
const HOSTNAME: &str = "picow";
|
||||
const WIRELESS_CREDENTIALS: &[(&str, &str)] =
|
||||
&include!(concat!(env!("OUT_DIR"), "/wireless-credentials.rs"));
|
||||
|
||||
// bind interrupt request to handler
|
||||
const WIRELESS_SCAN_PERIOD_SECOND: u64 = 7;
|
||||
|
||||
bind_interrupts!(struct Irqs {
|
||||
PIO0_IRQ_0 => pio::InterruptHandler<PIO0>;
|
||||
USBCTRL_IRQ => usb::InterruptHandler<USB>;
|
||||
});
|
||||
|
||||
// logger task
|
||||
#[embassy_executor::task]
|
||||
async fn logger_task(driver: Driver<'static, USB>) {
|
||||
embassy_usb_logger::run!(1024, log::LevelFilter::Info, driver);
|
||||
async fn logger_task(usb_driver: Driver<'static, USB>) -> ! {
|
||||
embassy_usb_logger::run!(1024, log::LevelFilter::Info, usb_driver);
|
||||
}
|
||||
|
||||
// wireless task
|
||||
#[embassy_executor::task]
|
||||
async fn cyw43_task(
|
||||
runner: cyw43::Runner<'static, Output<'static>, PioSpi<'static, PIO0, 0, DMA_CH0>>,
|
||||
async fn network_task(
|
||||
mut network_runner: embassy_net::Runner<'static, cyw43::NetDriver<'static>>,
|
||||
) -> ! {
|
||||
runner.run().await
|
||||
network_runner.run().await;
|
||||
}
|
||||
|
||||
#[embassy_executor::task]
|
||||
async fn wireless_task(
|
||||
wireless_runner: cyw43::Runner<'static, Output<'static>, PioSpi<'static, PIO0, 0, DMA_CH0>>,
|
||||
) -> ! {
|
||||
wireless_runner.run().await;
|
||||
}
|
||||
|
||||
#[embassy_executor::main]
|
||||
async fn main(spawner: Spawner) {
|
||||
async fn main(spawner: Spawner) -> ! {
|
||||
// hardware abstraction layer
|
||||
let hal = embassy_rp::init(Default::default());
|
||||
|
||||
// usb driver
|
||||
let driver = Driver::new(hal.USB, Irqs);
|
||||
let usb_driver = Driver::new(hal.USB, Irqs);
|
||||
|
||||
// spawn logger task
|
||||
spawner.spawn(logger_task(driver)).unwrap();
|
||||
spawner
|
||||
.spawn(logger_task(usb_driver))
|
||||
.expect("Logger task should not fail to spawn");
|
||||
|
||||
// wireless firmware binary
|
||||
let fw = include_bytes!("../firmware/43439A0.bin");
|
||||
|
|
@ -80,23 +95,69 @@ async fn main(spawner: Spawner) {
|
|||
let state = STATE.init(cyw43::State::new());
|
||||
|
||||
// spawn wireless task
|
||||
let (_, mut control, runner) = cyw43::new(state, pwr, spi, fw).await;
|
||||
spawner.spawn(cyw43_task(runner)).unwrap();
|
||||
let (network_device, mut wireless_control, wireless_runner) =
|
||||
cyw43::new(state, pwr, spi, fw).await;
|
||||
spawner
|
||||
.spawn(wireless_task(wireless_runner))
|
||||
.expect("Wireless task should not fail to spawn");
|
||||
|
||||
// initialize wireless
|
||||
control.init(clm).await;
|
||||
control
|
||||
// initialize wireless control
|
||||
wireless_control.init(clm).await;
|
||||
wireless_control
|
||||
.set_power_management(cyw43::PowerManagementMode::PowerSave)
|
||||
.await;
|
||||
|
||||
// time to blink
|
||||
let mut led = false;
|
||||
loop {
|
||||
for (k, v) in WIFI_CREDENTIALS {
|
||||
info!("{k}: {v}");
|
||||
// set hostname
|
||||
let mut dhcpv4_config = DhcpConfig::default();
|
||||
dhcpv4_config.hostname = HOSTNAME.try_into().ok();
|
||||
|
||||
// setup network stack
|
||||
static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new();
|
||||
let (network_stack, network_runner) = embassy_net::new(
|
||||
network_device,
|
||||
Config::dhcpv4(dhcpv4_config),
|
||||
RESOURCES.init(StackResources::new()),
|
||||
RoscRng.next_u64(),
|
||||
);
|
||||
|
||||
// spawn network task
|
||||
spawner
|
||||
.spawn(network_task(network_runner))
|
||||
.expect("Network task should not fail to spawn");
|
||||
|
||||
// search and join wireless network
|
||||
for (ssid, password) in WIRELESS_CREDENTIALS.iter().cycle() {
|
||||
info!("Searching for wireless network: {ssid}");
|
||||
if let Ok(_) = wireless_control
|
||||
.join(ssid, JoinOptions::new(password.as_bytes()))
|
||||
.await
|
||||
{
|
||||
info!("Successfully joined wireless network: {ssid}");
|
||||
break;
|
||||
} else if ssid
|
||||
== &WIRELESS_CREDENTIALS
|
||||
.last()
|
||||
.expect("The list of wireless credentials should not be empty")
|
||||
.0
|
||||
{
|
||||
info!("Unable to join any wireless network with provided credentials");
|
||||
info!("Sleep for {WIRELESS_SCAN_PERIOD_SECOND} seconds before rescan");
|
||||
Timer::after_secs(WIRELESS_SCAN_PERIOD_SECOND).await;
|
||||
}
|
||||
led = !led;
|
||||
control.gpio_set(0, led).await;
|
||||
}
|
||||
|
||||
// wait for network stack
|
||||
info!("Wait for network setup");
|
||||
network_stack.wait_config_up().await;
|
||||
network_stack.wait_link_up().await;
|
||||
info!("Successfully setup network stack");
|
||||
info!("Network configuration: {:?}", network_stack.config_v4());
|
||||
|
||||
// turn on led to indicate network connection
|
||||
wireless_control.gpio_set(0, true).await;
|
||||
|
||||
loop {
|
||||
info!("System is idle");
|
||||
Timer::after_secs(1).await;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue