forked from rp-rs/rp-hal
-
Notifications
You must be signed in to change notification settings - Fork 2
/
pico_w_blinky.rs
190 lines (152 loc) · 5.74 KB
/
pico_w_blinky.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
//! # Pico W Blinky Example
//!
//! Blinks the LED on a Pico W board.
//!
//! This will blink an LED attached to WL_GPIO0, which is the pin the Pico W uses for
//! the on-board LED. It is connected to the the Wifi chip so it cannot be set using RP2040 pins
//!
//! See the `Cargo.toml` file for Copyright and license details.
#![no_std]
#![no_main]
use rp_pico_w::entry;
use defmt::*;
use defmt_rtt as _;
use panic_probe as _;
use rp_pico_w::hal::pac;
use rp_pico_w::gspi::GSpi;
use rp_pico_w::hal;
use embedded_hal::digital::v2::OutputPin;
use embassy_executor::raw::TaskPool;
use embassy_executor::Executor;
use embassy_executor::Spawner;
use embassy_net::Stack;
use embassy_time::{Duration, Timer};
/// The function configures the RP2040 peripherals, initializes
/// networking, then blinks the LED in an infinite loop.
/// TODO: add some simple network service
#[entry]
fn main() -> ! {
info!("start");
// Grab our singleton objects
let mut pac = pac::Peripherals::take().unwrap();
// Set up the watchdog driver - needed by the clock setup code
let mut watchdog = hal::Watchdog::new(pac.WATCHDOG);
// Configure the clocks
//
// The default is to generate a 125 MHz system clock
let _clocks = hal::clocks::init_clocks_and_plls(
rp_pico_w::XOSC_CRYSTAL_FREQ,
pac.XOSC,
pac.CLOCKS,
pac.PLL_SYS,
pac.PLL_USB,
&mut pac.RESETS,
&mut watchdog,
)
.ok()
.unwrap();
let sio = hal::Sio::new(pac.SIO);
let pins = rp_pico_w::Pins::new(
pac.IO_BANK0,
pac.PADS_BANK0,
sio.gpio_bank0,
&mut pac.RESETS,
);
info!("init time driver");
let timer = hal::timer::Timer::new(pac.TIMER, &mut pac.RESETS);
unsafe { rp_pico_w::embassy_time_driver::init(timer) };
let mut executor = Executor::new();
// Safety: function never returns, executor is never dropped
let executor: &'static mut Executor = unsafe { forever_mut(&mut executor) };
let task_pool: TaskPool<_, 1> = TaskPool::new();
let task_pool = unsafe { forever(&task_pool) };
let state = cyw43::State::new();
let state = unsafe { forever(&state) };
info!("run spawner");
executor.run(|spawner| {
let spawn_token = task_pool.spawn(|| run(spawner, pins, state));
spawner.spawn(spawn_token).unwrap();
});
}
// TODO documentation
unsafe fn forever_mut<T>(r: &'_ mut T) -> &'static mut T {
core::mem::transmute(r)
}
// TODO documentation
unsafe fn forever<T>(r: &'_ T) -> &'static T {
core::mem::transmute(r)
}
async fn run(spawner: Spawner, pins: rp_pico_w::Pins, state: &'static cyw43::State) -> ! {
// These are implicitly used by the spi driver if they are in the correct mode
let mut spi_cs: hal::gpio::dynpin::DynPin = pins.wl_cs.into();
// TODO should be high from the beginning :-(
spi_cs.into_readable_output();
spi_cs.set_high().unwrap();
spi_cs.into_push_pull_output();
spi_cs.set_high().unwrap();
let mut spi_clk = pins.voltage_monitor_wl_clk.into_push_pull_output();
spi_clk.set_low().unwrap();
let mut spi_mosi_miso: hal::gpio::dynpin::DynPin = pins.wl_d.into();
spi_mosi_miso.into_readable_output();
spi_mosi_miso.set_low().unwrap();
spi_mosi_miso.into_push_pull_output();
spi_mosi_miso.set_low().unwrap();
let bus = GSpi::new(spi_clk, spi_mosi_miso);
let spi = embedded_hal_bus::spi::ExclusiveDevice::new(bus, spi_cs);
let pwr = pins.wl_on.into_push_pull_output();
let fw = cyw43::firmware::firmware();
let clm = cyw43::firmware::clm();
use embassy_futures::yield_now;
yield_now().await;
info!("create cyw43 driver");
let (mut control, runner) = cyw43::new(state, pwr, spi, fw).await;
let task_pool: TaskPool<_, 1> = TaskPool::new();
let task_pool = unsafe { forever(&task_pool) };
let spawn_token = task_pool.spawn(|| runner.run());
spawner.spawn(spawn_token).unwrap();
info!("init net net device");
let net_device = control.init(clm).await;
info!("init net net device done");
if option_env!("WIFI_NETWORK").is_some() {
if option_env!("WIFI_PASSWORD").is_some() {
control
.join_wpa2(
option_env!("WIFI_NETWORK").unwrap(),
option_env!("WIFI_PASSWORD").unwrap(),
)
.await;
} else {
control
.join_open(option_env!("WIFI_NETWORK").unwrap())
.await;
}
} else {
warn!("Environment variable WIFI_NETWORK not set during compilation - not joining wireless network");
}
let config = embassy_net::ConfigStrategy::Dhcp;
//let config = embassy_net::ConfigStrategy::Static(embassy_net::Config {
// address: Ipv4Cidr::new(Ipv4Address::new(192, 168, 69, 2), 24),
// dns_servers: Vec::new(),
// gateway: Some(Ipv4Address::new(192, 168, 69, 1)),
//});
// Generate random seed
let seed = 0x0123_4567_89ab_cdef; // chosen by fair dice roll. guarenteed to be random.
let mut stack_resources = embassy_net::StackResources::<1, 2, 8>::new();
let stack_resources = unsafe { forever_mut(&mut stack_resources) };
// Init network stack
let stack = Stack::new(net_device, config, stack_resources, seed);
let stack = unsafe { forever(&stack) };
let task_pool: TaskPool<_, 1> = TaskPool::new();
let task_pool = unsafe { forever(&task_pool) };
let spawn_token = task_pool.spawn(|| stack.run());
spawner.spawn(spawn_token).unwrap();
// Blink the LED at 1 Hz
loop {
info!("on");
control.gpio_set(0, true).await;
Timer::after(Duration::from_millis(500)).await;
info!("off");
control.gpio_set(0, false).await;
Timer::after(Duration::from_millis(500)).await;
}
}