mirror of
https://github.com/Djeeberjr/fw-anwesenheit.git
synced 2025-07-31 22:04:17 +00:00
improved project structure and hardware init
This commit is contained in:
parent
2e6094ea11
commit
c91d2f070f
61
src/bin/init/mod.rs
Normal file
61
src/bin/init/mod.rs
Normal file
@ -0,0 +1,61 @@
|
||||
use embassy_executor::Spawner;
|
||||
use embassy_net::Stack;
|
||||
use esp_hal::peripherals::{GPIO1, GPIO2, UART1};
|
||||
use esp_hal::{
|
||||
Async,
|
||||
clock::CpuClock,
|
||||
timer::{systimer::SystemTimer, timg::TimerGroup},
|
||||
uart::Uart,
|
||||
};
|
||||
use esp_println::logger::init_logger;
|
||||
use log::error;
|
||||
|
||||
mod network;
|
||||
mod wifi;
|
||||
|
||||
#[panic_handler]
|
||||
fn panic(_: &core::panic::PanicInfo) -> ! {
|
||||
loop {}
|
||||
}
|
||||
|
||||
esp_bootloader_esp_idf::esp_app_desc!();
|
||||
|
||||
pub async fn hardware_init(spawner: &mut Spawner) -> (Uart<'static, Async>, Stack<'static>) {
|
||||
let config = esp_hal::Config::default().with_cpu_clock(CpuClock::max());
|
||||
let peripherals = esp_hal::init(config);
|
||||
|
||||
esp_alloc::heap_allocator!(size: 72 * 1024);
|
||||
|
||||
let timer0 = SystemTimer::new(peripherals.SYSTIMER);
|
||||
esp_hal_embassy::init(timer0.alarm0);
|
||||
|
||||
init_logger(log::LevelFilter::Debug);
|
||||
|
||||
let timer1 = TimerGroup::new(peripherals.TIMG0);
|
||||
let mut rng = esp_hal::rng::Rng::new(peripherals.RNG);
|
||||
let network_seed = (rng.random() as u64) << 32 | rng.random() as u64;
|
||||
|
||||
wifi::set_antenna_mode(peripherals.GPIO3, peripherals.GPIO14).await;
|
||||
let interfaces = wifi::setup_wifi(timer1.timer0, rng, peripherals.WIFI, spawner);
|
||||
let stack = network::setup_network(network_seed, interfaces.ap, spawner);
|
||||
|
||||
let uart_devie = setup_uart(peripherals.UART1, peripherals.GPIO1, peripherals.GPIO2);
|
||||
|
||||
(uart_devie, stack)
|
||||
}
|
||||
|
||||
fn setup_uart(
|
||||
uart1: UART1<'static>,
|
||||
gpio1: GPIO1<'static>,
|
||||
gpio2: GPIO2<'static>,
|
||||
) -> Uart<'static, Async> {
|
||||
let uard_device = Uart::new(uart1, esp_hal::uart::Config::default().with_baudrate(9600));
|
||||
|
||||
match uard_device {
|
||||
Ok(block) => block.with_rx(gpio1).with_tx(gpio2).into_async(),
|
||||
Err(e) => {
|
||||
error!("Failed to initialize UART: {e}");
|
||||
panic!();
|
||||
}
|
||||
}
|
||||
}
|
72
src/bin/init/network.rs
Normal file
72
src/bin/init/network.rs
Normal file
@ -0,0 +1,72 @@
|
||||
use core::{net::Ipv4Addr, str::FromStr};
|
||||
|
||||
use embassy_executor::Spawner;
|
||||
use embassy_net::{Ipv4Cidr, Runner, Stack, StackResources, StaticConfigV4};
|
||||
use embassy_time::{Duration, Timer};
|
||||
use esp_wifi::wifi::WifiDevice;
|
||||
use static_cell::make_static;
|
||||
|
||||
|
||||
pub fn setup_network<'a>(seed: u64, wifi: WifiDevice<'static>, spawner: &mut Spawner) -> Stack<'a> {
|
||||
let gw_ip_addr_str = "192.168.2.1";
|
||||
let gw_ip_addr = Ipv4Addr::from_str(gw_ip_addr_str).expect("failed to parse gateway ip");
|
||||
let config = embassy_net::Config::ipv4_static(StaticConfigV4 {
|
||||
address: Ipv4Cidr::new(gw_ip_addr, 24),
|
||||
gateway: Some(gw_ip_addr),
|
||||
dns_servers: Default::default(),
|
||||
});
|
||||
|
||||
let (stack, runner) =
|
||||
embassy_net::new(wifi, config, make_static!(StackResources::<3>::new()), seed);
|
||||
|
||||
spawner.must_spawn(net_task(runner));
|
||||
spawner.must_spawn(run_dhcp(stack, gw_ip_addr_str));
|
||||
|
||||
stack
|
||||
}
|
||||
|
||||
#[embassy_executor::task]
|
||||
async fn run_dhcp(stack: Stack<'static>, gw_ip_addr: &'static str) {
|
||||
use core::net::{Ipv4Addr, SocketAddrV4};
|
||||
|
||||
use edge_dhcp::{
|
||||
io::{self, DEFAULT_SERVER_PORT},
|
||||
server::{Server, ServerOptions},
|
||||
};
|
||||
use edge_nal::UdpBind;
|
||||
use edge_nal_embassy::{Udp, UdpBuffers};
|
||||
|
||||
let ip = Ipv4Addr::from_str(gw_ip_addr).expect("dhcp task failed to parse gw ip");
|
||||
|
||||
let mut buf = [0u8; 1500];
|
||||
|
||||
let mut gw_buf = [Ipv4Addr::UNSPECIFIED];
|
||||
|
||||
let buffers = UdpBuffers::<3, 1024, 1024, 10>::new();
|
||||
let unbound_socket = Udp::new(stack, &buffers);
|
||||
let mut bound_socket = unbound_socket
|
||||
.bind(core::net::SocketAddr::V4(SocketAddrV4::new(
|
||||
Ipv4Addr::UNSPECIFIED,
|
||||
DEFAULT_SERVER_PORT,
|
||||
)))
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
loop {
|
||||
_ = io::server::run(
|
||||
&mut Server::<_, 64>::new_with_et(ip),
|
||||
&ServerOptions::new(ip, Some(&mut gw_buf)),
|
||||
&mut bound_socket,
|
||||
&mut buf,
|
||||
)
|
||||
.await
|
||||
.inspect_err(|e| log::warn!("DHCP server error: {e:?}"));
|
||||
Timer::after(Duration::from_millis(500)).await;
|
||||
}
|
||||
}
|
||||
|
||||
#[embassy_executor::task]
|
||||
async fn net_task(mut runner: Runner<'static, WifiDevice<'static>>) {
|
||||
runner.run().await;
|
||||
}
|
||||
|
56
src/bin/init/wifi.rs
Normal file
56
src/bin/init/wifi.rs
Normal file
@ -0,0 +1,56 @@
|
||||
use embassy_executor::Spawner;
|
||||
use embassy_time::{Duration, Timer};
|
||||
use esp_hal::gpio::{Output, OutputConfig};
|
||||
use esp_hal::peripherals::{GPIO3, GPIO14, WIFI};
|
||||
use esp_wifi::wifi::{AccessPointConfiguration, Configuration, WifiController, WifiEvent, WifiState};
|
||||
use esp_wifi::{EspWifiRngSource, EspWifiTimerSource, wifi::Interfaces};
|
||||
use static_cell::make_static;
|
||||
|
||||
pub async fn set_antenna_mode(gpio3: GPIO3<'static>, gpio14: GPIO14<'static>) {
|
||||
let mut rf_switch = Output::new(gpio3, esp_hal::gpio::Level::Low, OutputConfig::default());
|
||||
|
||||
rf_switch.set_low();
|
||||
|
||||
Timer::after_millis(150).await;
|
||||
|
||||
let mut antenna_mode = Output::new(gpio14, esp_hal::gpio::Level::Low, OutputConfig::default());
|
||||
|
||||
antenna_mode.set_low();
|
||||
}
|
||||
|
||||
pub fn setup_wifi<'d: 'static>(
|
||||
timer: impl EspWifiTimerSource + 'd,
|
||||
rng: impl EspWifiRngSource + 'd,
|
||||
wifi: WIFI<'static>,
|
||||
spawner: &mut Spawner,
|
||||
) -> Interfaces<'d> {
|
||||
let esp_wifi_ctrl = make_static!(esp_wifi::init(timer, rng).unwrap());
|
||||
|
||||
let (controller, interfaces) = esp_wifi::wifi::new(esp_wifi_ctrl, wifi).unwrap();
|
||||
|
||||
spawner.must_spawn(connection(controller));
|
||||
|
||||
interfaces
|
||||
}
|
||||
|
||||
#[embassy_executor::task]
|
||||
async fn connection(mut controller: WifiController<'static>) {
|
||||
loop {
|
||||
match esp_wifi::wifi::wifi_state() {
|
||||
WifiState::ApStarted => {
|
||||
// wait until we're no longer connected
|
||||
controller.wait_for_event(WifiEvent::ApStop).await;
|
||||
Timer::after(Duration::from_millis(5000)).await
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
if !matches!(controller.is_started(), Ok(true)) {
|
||||
let client_config = Configuration::AccessPoint(AccessPointConfiguration {
|
||||
ssid: "esp-wifi".try_into().unwrap(),
|
||||
..Default::default()
|
||||
});
|
||||
controller.set_configuration(&client_config).unwrap();
|
||||
controller.start_async().await.unwrap();
|
||||
}
|
||||
}
|
||||
}
|
250
src/bin/main.rs
250
src/bin/main.rs
@ -3,115 +3,29 @@
|
||||
#![feature(type_alias_impl_trait)]
|
||||
#![feature(impl_trait_in_assoc_type)]
|
||||
|
||||
use core::net::Ipv4Addr;
|
||||
use core::str::FromStr;
|
||||
|
||||
use embassy_executor::Spawner;
|
||||
use embassy_net::{Ipv4Cidr, Runner, Stack, StackResources, StaticConfigV4};
|
||||
use embassy_net::Stack;
|
||||
use embassy_time::{Duration, Timer};
|
||||
use esp_hal::clock::CpuClock;
|
||||
use esp_hal::gpio::{Output, OutputConfig};
|
||||
use esp_hal::peripherals::{GPIO1, GPIO2, UART1};
|
||||
use esp_hal::timer::systimer::SystemTimer;
|
||||
use esp_hal::timer::timg::TimerGroup;
|
||||
use esp_hal::uart::{Config, Uart};
|
||||
use esp_println::logger::init_logger;
|
||||
use esp_wifi::wifi::{
|
||||
AccessPointConfiguration, Configuration, WifiController, WifiDevice, WifiEvent, WifiState,
|
||||
};
|
||||
use esp_hal::Async;
|
||||
use esp_hal::uart::Uart;
|
||||
use log::{debug, info};
|
||||
use picoserve::routing::get;
|
||||
use picoserve::{AppBuilder, AppRouter};
|
||||
use static_cell::make_static;
|
||||
|
||||
#[panic_handler]
|
||||
fn panic(_: &core::panic::PanicInfo) -> ! {
|
||||
loop {}
|
||||
}
|
||||
use crate::webserver::start_webserver;
|
||||
|
||||
extern crate alloc;
|
||||
|
||||
esp_bootloader_esp_idf::esp_app_desc!();
|
||||
mod init;
|
||||
mod webserver;
|
||||
|
||||
#[esp_hal_embassy::main]
|
||||
async fn main(spawner: Spawner) {
|
||||
// ------------------- init ---------------------------
|
||||
let config = esp_hal::Config::default().with_cpu_clock(CpuClock::max());
|
||||
let peripherals = esp_hal::init(config);
|
||||
async fn main(mut spawner: Spawner) {
|
||||
let (uart_device, stack) = init::hardware_init(&mut spawner).await;
|
||||
|
||||
info!("starting up...");
|
||||
wait_for_stack_up(stack).await;
|
||||
|
||||
esp_alloc::heap_allocator!(size: 72 * 1024);
|
||||
|
||||
let timer0 = SystemTimer::new(peripherals.SYSTIMER);
|
||||
esp_hal_embassy::init(timer0.alarm0);
|
||||
|
||||
init_logger(log::LevelFilter::Debug);
|
||||
|
||||
let timer1 = TimerGroup::new(peripherals.TIMG0);
|
||||
let mut rng = esp_hal::rng::Rng::new(peripherals.RNG);
|
||||
|
||||
debug!("set wlan antenna..");
|
||||
let mut rf_switch = Output::new(
|
||||
peripherals.GPIO3,
|
||||
esp_hal::gpio::Level::Low,
|
||||
OutputConfig::default(),
|
||||
);
|
||||
|
||||
rf_switch.set_low();
|
||||
|
||||
Timer::after_secs(1).await;
|
||||
|
||||
let mut antenna_mode = Output::new(
|
||||
peripherals.GPIO14,
|
||||
esp_hal::gpio::Level::Low,
|
||||
OutputConfig::default(),
|
||||
);
|
||||
|
||||
antenna_mode.set_low();
|
||||
|
||||
Timer::after_secs(1).await;
|
||||
|
||||
// Setup wifi deivce
|
||||
debug!("setup wifi..");
|
||||
let esp_wifi_ctrl =
|
||||
make_static!(esp_wifi::init(timer1.timer0, rng).unwrap());
|
||||
let (controller, interfaces) = esp_wifi::wifi::new(esp_wifi_ctrl, peripherals.WIFI).unwrap();
|
||||
// let wifi_interface = interfaces.sta;
|
||||
let wifi_ap = interfaces.ap;
|
||||
|
||||
let gw_ip_addr_str = "192.168.2.1";
|
||||
let gw_ip_addr = Ipv4Addr::from_str(gw_ip_addr_str).expect("failed to parse gateway ip");
|
||||
|
||||
let config = embassy_net::Config::ipv4_static(StaticConfigV4 {
|
||||
address: Ipv4Cidr::new(gw_ip_addr, 24),
|
||||
gateway: Some(gw_ip_addr),
|
||||
dns_servers: Default::default(),
|
||||
});
|
||||
|
||||
let seed = (rng.random() as u64) << 32 | rng.random() as u64;
|
||||
|
||||
// Init network stack
|
||||
let (stack, runner) = embassy_net::new(
|
||||
wifi_ap,
|
||||
config,
|
||||
make_static!(StackResources::<3>::new()),
|
||||
seed,
|
||||
);
|
||||
|
||||
debug!("Setup complete. Running network tasks");
|
||||
|
||||
spawner.spawn(connection(controller)).ok();
|
||||
spawner.spawn(net_task(runner)).ok();
|
||||
spawner.spawn(run_dhcp(stack, gw_ip_addr_str)).ok();
|
||||
spawner
|
||||
.spawn(rfid_reader_task(
|
||||
peripherals.UART1,
|
||||
peripherals.GPIO1,
|
||||
peripherals.GPIO2,
|
||||
))
|
||||
.ok();
|
||||
start_webserver(&mut spawner, stack);
|
||||
spawner.must_spawn(rfid_reader_task(uart_device));
|
||||
}
|
||||
|
||||
async fn wait_for_stack_up(stack: Stack<'static>) {
|
||||
loop {
|
||||
if stack.is_link_up() {
|
||||
break;
|
||||
@ -122,154 +36,24 @@ async fn main(spawner: Spawner) {
|
||||
}
|
||||
Timer::after(Duration::from_millis(500)).await;
|
||||
}
|
||||
|
||||
debug!("Starting webserver");
|
||||
|
||||
let app = make_static!(AppProps.build_app());
|
||||
|
||||
let config = make_static!(picoserve::Config::new(picoserve::Timeouts {
|
||||
start_read_request: Some(Duration::from_secs(5)),
|
||||
persistent_start_read_request: Some(Duration::from_secs(1)),
|
||||
read_request: Some(Duration::from_secs(1)),
|
||||
write: Some(Duration::from_secs(1)),
|
||||
}));
|
||||
|
||||
let _ = spawner.spawn(webserver_task(0, stack, app, config));
|
||||
}
|
||||
|
||||
struct AppProps;
|
||||
|
||||
impl AppBuilder for AppProps {
|
||||
type PathRouter = impl picoserve::routing::PathRouter;
|
||||
|
||||
fn build_app(self) -> picoserve::Router<Self::PathRouter> {
|
||||
picoserve::Router::new().route("/", get(|| async move { "Hello World" }))
|
||||
}
|
||||
}
|
||||
|
||||
#[embassy_executor::task]
|
||||
async fn webserver_task(
|
||||
id: usize,
|
||||
stack: embassy_net::Stack<'static>,
|
||||
app: &'static AppRouter<AppProps>,
|
||||
config: &'static picoserve::Config<Duration>,
|
||||
) -> ! {
|
||||
let mut tcp_rx_buffer = [0u8; 1024];
|
||||
let mut tcp_tx_buffer = [0u8; 1024];
|
||||
let mut http_buffer = [0u8; 2048];
|
||||
|
||||
picoserve::listen_and_serve(
|
||||
id,
|
||||
app,
|
||||
config,
|
||||
stack,
|
||||
80,
|
||||
&mut tcp_rx_buffer,
|
||||
&mut tcp_tx_buffer,
|
||||
&mut http_buffer,
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
#[embassy_executor::task]
|
||||
async fn run_dhcp(stack: Stack<'static>, gw_ip_addr: &'static str) {
|
||||
debug!("start dhcp");
|
||||
use core::net::{Ipv4Addr, SocketAddrV4};
|
||||
|
||||
use edge_dhcp::{
|
||||
io::{self, DEFAULT_SERVER_PORT},
|
||||
server::{Server, ServerOptions},
|
||||
};
|
||||
use edge_nal::UdpBind;
|
||||
use edge_nal_embassy::{Udp, UdpBuffers};
|
||||
|
||||
let ip = Ipv4Addr::from_str(gw_ip_addr).expect("dhcp task failed to parse gw ip");
|
||||
|
||||
let mut buf = [0u8; 1500];
|
||||
|
||||
let mut gw_buf = [Ipv4Addr::UNSPECIFIED];
|
||||
|
||||
let buffers = UdpBuffers::<3, 1024, 1024, 10>::new();
|
||||
let unbound_socket = Udp::new(stack, &buffers);
|
||||
let mut bound_socket = unbound_socket
|
||||
.bind(core::net::SocketAddr::V4(SocketAddrV4::new(
|
||||
Ipv4Addr::UNSPECIFIED,
|
||||
DEFAULT_SERVER_PORT,
|
||||
)))
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
loop {
|
||||
_ = io::server::run(
|
||||
&mut Server::<_, 64>::new_with_et(ip),
|
||||
&ServerOptions::new(ip, Some(&mut gw_buf)),
|
||||
&mut bound_socket,
|
||||
&mut buf,
|
||||
)
|
||||
.await
|
||||
.inspect_err(|e| log::warn!("DHCP server error: {e:?}"));
|
||||
Timer::after(Duration::from_millis(500)).await;
|
||||
}
|
||||
}
|
||||
|
||||
#[embassy_executor::task]
|
||||
async fn net_task(mut runner: Runner<'static, WifiDevice<'static>>) {
|
||||
runner.run().await;
|
||||
}
|
||||
|
||||
#[embassy_executor::task]
|
||||
async fn connection(mut controller: WifiController<'static>) {
|
||||
debug!("start connection task");
|
||||
debug!("Device capabilities: {:?}", controller.capabilities());
|
||||
loop {
|
||||
match esp_wifi::wifi::wifi_state() {
|
||||
WifiState::ApStarted => {
|
||||
// wait until we're no longer connected
|
||||
controller.wait_for_event(WifiEvent::ApStop).await;
|
||||
Timer::after(Duration::from_millis(5000)).await
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
if !matches!(controller.is_started(), Ok(true)) {
|
||||
let client_config = Configuration::AccessPoint(AccessPointConfiguration {
|
||||
ssid: "esp-wifi".try_into().unwrap(),
|
||||
..Default::default()
|
||||
});
|
||||
controller.set_configuration(&client_config).unwrap();
|
||||
debug!("Starting wifi");
|
||||
controller.start_async().await.unwrap();
|
||||
debug!("Wifi started!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[embassy_executor::task]
|
||||
async fn rfid_reader_task(uart1: UART1<'static>, gpio1: GPIO1<'static>, gpio2: GPIO2<'static>) {
|
||||
debug!("init rfid reader..");
|
||||
|
||||
let uart1_block_result = Uart::new(uart1, Config::default().with_baudrate(9600));
|
||||
let mut nfc_reader = match uart1_block_result {
|
||||
Ok(block) => block.with_rx(gpio1).with_tx(gpio2).into_async(),
|
||||
Err(e) => {
|
||||
log::error!("Failed to initialize UART: {:?}", e);
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
async fn rfid_reader_task(mut uart_device: Uart<'static, Async>) {
|
||||
let mut uart_buffer = [0u8; 64];
|
||||
|
||||
loop {
|
||||
debug!("Looking for NFC...");
|
||||
match nfc_reader.read_async(&mut uart_buffer).await {
|
||||
match uart_device.read_async(&mut uart_buffer).await {
|
||||
Ok(n) => {
|
||||
let mut hex_str = heapless::String::<128>::new();
|
||||
for byte in &uart_buffer[..n] {
|
||||
core::fmt::Write::write_fmt(&mut hex_str, format_args!("{:02X} ", byte)).ok();
|
||||
}
|
||||
info!("Read {} bytes from UART: {}", n, hex_str);
|
||||
info!("Read {n} bytes from UART: {hex_str}");
|
||||
}
|
||||
Err(e) => {
|
||||
log::error!("Error reading from UART: {:?}", e);
|
||||
log::error!("Error reading from UART: {e}");
|
||||
}
|
||||
}
|
||||
Timer::after(Duration::from_millis(200)).await;
|
||||
|
52
src/bin/webserver/mod.rs
Normal file
52
src/bin/webserver/mod.rs
Normal file
@ -0,0 +1,52 @@
|
||||
use embassy_executor::Spawner;
|
||||
use embassy_net::Stack;
|
||||
use embassy_time::Duration;
|
||||
use picoserve::{AppBuilder, AppRouter, routing::get};
|
||||
use static_cell::make_static;
|
||||
|
||||
pub fn start_webserver(spawner: &mut Spawner, stack: Stack<'static>) {
|
||||
let app = make_static!(AppProps.build_app());
|
||||
|
||||
let config = make_static!(picoserve::Config::new(picoserve::Timeouts {
|
||||
start_read_request: Some(Duration::from_secs(5)),
|
||||
persistent_start_read_request: Some(Duration::from_secs(1)),
|
||||
read_request: Some(Duration::from_secs(1)),
|
||||
write: Some(Duration::from_secs(1)),
|
||||
}));
|
||||
|
||||
let _ = spawner.spawn(webserver_task(0, stack, app, config));
|
||||
}
|
||||
|
||||
struct AppProps;
|
||||
|
||||
impl AppBuilder for AppProps {
|
||||
type PathRouter = impl picoserve::routing::PathRouter;
|
||||
|
||||
fn build_app(self) -> picoserve::Router<Self::PathRouter> {
|
||||
picoserve::Router::new().route("/", get(|| async move { "Hello World" }))
|
||||
}
|
||||
}
|
||||
|
||||
#[embassy_executor::task]
|
||||
async fn webserver_task(
|
||||
id: usize,
|
||||
stack: embassy_net::Stack<'static>,
|
||||
app: &'static AppRouter<AppProps>,
|
||||
config: &'static picoserve::Config<Duration>,
|
||||
) -> ! {
|
||||
let mut tcp_rx_buffer = [0u8; 1024];
|
||||
let mut tcp_tx_buffer = [0u8; 1024];
|
||||
let mut http_buffer = [0u8; 2048];
|
||||
|
||||
picoserve::listen_and_serve(
|
||||
id,
|
||||
app,
|
||||
config,
|
||||
stack,
|
||||
80,
|
||||
&mut tcp_rx_buffer,
|
||||
&mut tcp_tx_buffer,
|
||||
&mut http_buffer,
|
||||
)
|
||||
.await
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user