The Pico W now serves a basic HTML page.
This has not been so simple. The only way I could find to make picoserve and embassy compatible was to get a local copy of picoserve and change its embassy dependencies to use git as their source. Otherwise there are conflicts about embassy-timer-driver versions. Using picoserve also required changing my Rust "channel" to "nightly". A bunch of stuff I am not keen on, but necessary to progress rather than get bogged down in build system meta. Meanwhile also I've changed this to use a static IP at 192.168.3.14 for now. For currently unknownr reasons the loop waiting for the DHCP lease to work isn't exiting. I have rebooted the DHCP server and that didn't help and given the WiFi on the Pico W is working I don't really know whats up.
This commit is contained in:
parent
f5ce5e7958
commit
bd9389cfd5
7 changed files with 1039 additions and 323 deletions
1210
Cargo.lock
generated
1210
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
|
|
@ -7,6 +7,8 @@ version = "0.1.0"
|
|||
license = "MIT OR Apache-2.0"
|
||||
|
||||
[dependencies]
|
||||
# web server
|
||||
picoserve = { version = "0.15.0", path = "../picoserve/picoserve/", features = ["embassy"] }
|
||||
embassy-embedded-hal = { version = "0.3.0", git = "https://github.com/embassy-rs/embassy.git", features = ["defmt"] }
|
||||
embassy-sync = { version = "0.6.2", git = "https://github.com/embassy-rs/embassy.git", features = ["defmt"] }
|
||||
embassy-executor = { version = "0.7.0", git = "https://github.com/embassy-rs/embassy.git", features = ["task-arena-size-98304", "arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] }
|
||||
|
|
@ -25,13 +27,14 @@ defmt-rtt = "0.4"
|
|||
fixed = "1.23.1"
|
||||
fixed-macro = "1.2"
|
||||
|
||||
|
||||
# for web request example
|
||||
#reqwless = { version = "0.13.0", features = ["defmt"] }
|
||||
#serde = { version = "1.0.203", default-features = false, features = ["derive"] }
|
||||
#serde-json-core = "0.5.1"
|
||||
|
||||
# for assign resources example
|
||||
#assign-resources = { git = "https://github.com/adamgreig/assign-resources", rev = "94ad10e2729afdf0fd5a77cd12e68409a982f58a" }
|
||||
#assign-resources = { rev = "94ad10e2729afdf0fd5a77cd12e68409a982f58a" }
|
||||
|
||||
#cortex-m = { version = "0.7.6", features = ["critical-section-single-core"] }
|
||||
cortex-m = { version = "0.7.6", features = ["inline-asm"] }
|
||||
|
|
|
|||
12
memory.x
12
memory.x
|
|
@ -1,17 +1,5 @@
|
|||
MEMORY {
|
||||
BOOT2 : ORIGIN = 0x10000000, LENGTH = 0x100
|
||||
FLASH : ORIGIN = 0x10000100, LENGTH = 2048K - 0x100
|
||||
|
||||
/* Pick one of the two options for RAM layout */
|
||||
|
||||
/* OPTION A: Use all RAM banks as one big block */
|
||||
/* Reasonable, unless you are doing something */
|
||||
/* really particular with DMA or other concurrent */
|
||||
/* access that would benefit from striping */
|
||||
RAM : ORIGIN = 0x20000000, LENGTH = 264K
|
||||
|
||||
/* OPTION B: Keep the unstriped sections separate */
|
||||
/* RAM: ORIGIN = 0x20000000, LENGTH = 256K */
|
||||
/* SCRATCH_A: ORIGIN = 0x20040000, LENGTH = 4K */
|
||||
/* SCRATCH_B: ORIGIN = 0x20041000, LENGTH = 4K */
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
[toolchain]
|
||||
channel = "1.84"
|
||||
channel = "nightly"
|
||||
components = [ "rust-src", "rustfmt", "llvm-tools" ]
|
||||
targets = [
|
||||
"thumbv6m-none-eabi",
|
||||
|
|
|
|||
12
src/html/index.html
Normal file
12
src/html/index.html
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Meat-Pi</title>
|
||||
<link rel="stylesheet" href="main.css">
|
||||
</head>
|
||||
<body>
|
||||
<h1>Meat-Pi 🍖🌡️</h1>
|
||||
</body>
|
||||
</html>
|
||||
19
src/html/main.css
Normal file
19
src/html/main.css
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
:root {
|
||||
color-scheme: light dark;
|
||||
--light-bg: #ddffdd;
|
||||
--light-color: #002200;
|
||||
--dark-bg: #002200;
|
||||
--dark-color: #ddffdd;
|
||||
}
|
||||
|
||||
* {
|
||||
background-color: light-dark(var(--light-bg), var(--dark-bg));
|
||||
color: light-dark(var(--light-color), var(--dark-color));
|
||||
}
|
||||
|
||||
body {
|
||||
display: flex;
|
||||
flex-flow: column nowrap;
|
||||
align-items: center;
|
||||
font-family: Arial, sans-serif;
|
||||
}
|
||||
98
src/main.rs
98
src/main.rs
|
|
@ -1,17 +1,14 @@
|
|||
//! This example test the RP Pico W on board LED.
|
||||
//!
|
||||
//! It does not work with the RP Pico board. See blinky.rs.
|
||||
//! Raspberry Pi Pico W meat thermometer
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use core::str::from_utf8;
|
||||
// required for impl in AppProps code for picoserve
|
||||
#![feature(impl_trait_in_assoc_type)]
|
||||
|
||||
use cyw43::JoinOptions;
|
||||
use cyw43_pio::{PioSpi, DEFAULT_CLOCK_DIVIDER};
|
||||
use embassy_executor::Spawner;
|
||||
use embassy_net::{Config, StackResources};
|
||||
use embassy_net::tcp::TcpSocket;
|
||||
use embassy_net::{Config, StackResources, Ipv4Cidr, Ipv4Address};
|
||||
use embassy_rp::bind_interrupts;
|
||||
use embassy_rp::clocks::RoscRng;
|
||||
use embassy_rp::gpio::{Level, Output};
|
||||
|
|
@ -20,7 +17,13 @@ use embassy_rp::peripherals::USB;
|
|||
use embassy_rp::pio::{InterruptHandler, Pio};
|
||||
use embassy_rp::usb::{Driver, InterruptHandler as USBInterruptHandler};
|
||||
use embassy_time::{Duration, Timer};
|
||||
use embedded_io_async::Write;
|
||||
use heapless::Vec;
|
||||
use picoserve::{
|
||||
make_static,
|
||||
routing::{get_service, PathRouter},
|
||||
AppBuilder, AppRouter
|
||||
};
|
||||
use picoserve::response::File;
|
||||
use rand::RngCore;
|
||||
use static_cell::StaticCell;
|
||||
use {defmt_rtt as _, panic_probe as _};
|
||||
|
|
@ -51,6 +54,54 @@ async fn net_task(mut runner: embassy_net::Runner<'static, cyw43::NetDriver<'sta
|
|||
runner.run().await
|
||||
}
|
||||
|
||||
|
||||
// picoserve HTTP code kicked off using: https://github.com/sammhicks/picoserve/blob/main/examples/embassy/hello_world/src/main.rs
|
||||
struct AppProps;
|
||||
|
||||
impl AppBuilder for AppProps {
|
||||
type PathRouter = impl PathRouter;
|
||||
|
||||
fn build_app(self) -> picoserve::Router<Self::PathRouter> {
|
||||
picoserve::Router::new()
|
||||
.route(
|
||||
"/",
|
||||
get_service(File::html(include_str!("html/index.html")))
|
||||
)
|
||||
.route(
|
||||
"/main.css",
|
||||
get_service(File::css(include_str!("html/main.css")))
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// 2 is plenty of a little IoT thermometer, right?
|
||||
const WEB_TASK_POOL_SIZE: usize = 2;
|
||||
|
||||
#[embassy_executor::task(pool_size = WEB_TASK_POOL_SIZE)]
|
||||
async fn web_task(
|
||||
id: usize,
|
||||
stack: embassy_net::Stack<'static>,
|
||||
app: &'static AppRouter<AppProps>,
|
||||
config: &'static picoserve::Config<Duration>,
|
||||
) -> ! {
|
||||
let port = 80;
|
||||
let mut tcp_rx_buffer = [0; 1024];
|
||||
let mut tcp_tx_buffer = [0; 1024];
|
||||
let mut http_buffer = [0; 2048];
|
||||
|
||||
picoserve::listen_and_serve(
|
||||
id,
|
||||
app,
|
||||
config,
|
||||
stack,
|
||||
port,
|
||||
&mut tcp_rx_buffer,
|
||||
&mut tcp_tx_buffer,
|
||||
&mut http_buffer,
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
#[embassy_executor::main]
|
||||
async fn main(spawner: Spawner) {
|
||||
let p = embassy_rp::init(Default::default());
|
||||
|
|
@ -102,7 +153,12 @@ async fn main(spawner: Spawner) {
|
|||
.set_power_management(cyw43::PowerManagementMode::PowerSave)
|
||||
.await;
|
||||
|
||||
let config = Config::dhcpv4(Default::default());
|
||||
//let config = Config::dhcpv4(Default::default());
|
||||
let config = embassy_net::Config::ipv4_static(embassy_net::StaticConfigV4 {
|
||||
address: Ipv4Cidr::new(Ipv4Address::new(192, 168, 3, 14), 24),
|
||||
dns_servers: Vec::new(),
|
||||
gateway: Some(Ipv4Address::new(192, 168, 3, 1)),
|
||||
});
|
||||
|
||||
// Generate random seed
|
||||
let seed = rng.next_u64();
|
||||
|
|
@ -126,18 +182,35 @@ async fn main(spawner: Spawner) {
|
|||
}
|
||||
|
||||
// Wait for DHCP, not necessary when using static IP
|
||||
log::info!("waiting for DHCP...");
|
||||
/*log::info!("waiting for DHCP...");
|
||||
while !stack.is_config_up() {
|
||||
Timer::after_millis(100).await;
|
||||
}
|
||||
log::info!("DHCP is now up!");
|
||||
log::info!("DHCP is now up!");*/
|
||||
|
||||
// And now we can use it!
|
||||
let app = make_static!(AppRouter<AppProps>, AppProps.build_app());
|
||||
|
||||
let config = make_static!(
|
||||
picoserve::Config<Duration>,
|
||||
picoserve::Config::new(picoserve::Timeouts {
|
||||
start_read_request: Some(Duration::from_secs(5)),
|
||||
read_request: Some(Duration::from_secs(1)),
|
||||
write: Some(Duration::from_secs(1)),
|
||||
})
|
||||
.keep_connection_alive()
|
||||
);
|
||||
|
||||
for id in 0..WEB_TASK_POOL_SIZE {
|
||||
spawner.must_spawn(web_task(id, stack, app, config));
|
||||
}
|
||||
/*
|
||||
let mut rx_buffer = [0; 4096];
|
||||
let mut tx_buffer = [0; 4096];
|
||||
let mut buf = [0; 4096];
|
||||
|
||||
let mut socket = TcpSocket::new(stack, &mut rx_buffer, &mut tx_buffer);
|
||||
|
||||
//let delay = Duration::from_secs(1);
|
||||
log::info!("main: pre-loop");
|
||||
loop {
|
||||
|
|
@ -145,7 +218,7 @@ async fn main(spawner: Spawner) {
|
|||
socket.set_timeout(Some(Duration::from_secs(10)));
|
||||
|
||||
control.gpio_set(0, false).await;
|
||||
log::info!("Listening on TCP:1234...");
|
||||
log::info!("Listening on TCP:00...");
|
||||
if let Err(e) = socket.accept(1234).await {
|
||||
log::warn!("accept error: {:?}", e);
|
||||
continue;
|
||||
|
|
@ -183,4 +256,5 @@ async fn main(spawner: Spawner) {
|
|||
log::info!("LED off!");
|
||||
control.gpio_set(0, false).await;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue