#![no_std] #![no_main] #![feature(type_alias_impl_trait)] use defmt::*; use embassy_executor::Spawner; use embassy_net::tcp::TcpSocket; use embassy_net::{Ipv4Address, Stack, StackResources}; use embassy_stm32::eth::generic_smi::GenericSMI; use embassy_stm32::eth::{Ethernet, PacketQueue}; use embassy_stm32::peripherals::ETH; use embassy_stm32::rcc::{ AHBPrescaler, APBPrescaler, Hse, HseMode, Pll, PllDiv, PllMul, PllPreDiv, PllSource, Sysclk, VoltageScale, }; use embassy_stm32::rng::Rng; use embassy_stm32::time::Hertz; use embassy_stm32::{bind_interrupts, eth, peripherals, rng, Config}; use embassy_time::{Duration, Timer}; use embedded_io_async::Write; use rand_core::RngCore; use static_cell::make_static; use {defmt_rtt as _, panic_probe as _}; bind_interrupts!(struct Irqs { ETH => eth::InterruptHandler; RNG => rng::InterruptHandler; }); type Device = Ethernet<'static, ETH, GenericSMI>; #[embassy_executor::task] async fn net_task(stack: &'static Stack) -> ! { stack.run().await } #[embassy_executor::main] async fn main(spawner: Spawner) -> ! { let mut config = Config::default(); config.rcc.hsi = None; config.rcc.hsi48 = true; // needed for rng config.rcc.hse = Some(Hse { freq: Hertz(8_000_000), mode: HseMode::BypassDigital, }); config.rcc.pll1 = Some(Pll { source: PllSource::Hse, prediv: PllPreDiv::DIV2, mul: PllMul::MUL125, divp: Some(PllDiv::DIV2), divq: Some(PllDiv::DIV2), divr: None, }); config.rcc.ahb_pre = AHBPrescaler::DIV1; config.rcc.apb1_pre = APBPrescaler::DIV1; config.rcc.apb2_pre = APBPrescaler::DIV1; config.rcc.apb3_pre = APBPrescaler::DIV1; config.rcc.sys = Sysclk::Pll1P; config.rcc.voltage_scale = VoltageScale::Scale0; let p = embassy_stm32::init(config); info!("Hello World!"); // Generate random seed. let mut rng = Rng::new(p.RNG, Irqs); let mut seed = [0; 8]; rng.fill_bytes(&mut seed); let seed = u64::from_le_bytes(seed); let mac_addr = [0x00, 0x00, 0xDE, 0xAD, 0xBE, 0xEF]; let device = Ethernet::new( make_static!(PacketQueue::<4, 4>::new()), p.ETH, Irqs, p.PA1, p.PA2, p.PC1, p.PA7, p.PC4, p.PC5, p.PG13, p.PB15, p.PG11, GenericSMI::new(), mac_addr, 0, ); let config = embassy_net::Config::dhcpv4(Default::default()); //let config = embassy_net::Config::ipv4_static(embassy_net::StaticConfigV4 { // address: Ipv4Cidr::new(Ipv4Address::new(10, 42, 0, 61), 24), // dns_servers: Vec::new(), // gateway: Some(Ipv4Address::new(10, 42, 0, 1)), //}); // Init network stack let stack = &*make_static!(Stack::new( device, config, make_static!(StackResources::<2>::new()), seed )); // Launch network task unwrap!(spawner.spawn(net_task(&stack))); // Ensure DHCP configuration is up before trying connect stack.wait_config_up().await; info!("Network task initialized"); // Then we can use it! let mut rx_buffer = [0; 1024]; let mut tx_buffer = [0; 1024]; loop { let mut socket = TcpSocket::new(&stack, &mut rx_buffer, &mut tx_buffer); socket.set_timeout(Some(embassy_time::Duration::from_secs(10))); let remote_endpoint = (Ipv4Address::new(10, 42, 0, 1), 8000); info!("connecting..."); let r = socket.connect(remote_endpoint).await; if let Err(e) = r { info!("connect error: {:?}", e); Timer::after(Duration::from_secs(3)).await; continue; } info!("connected!"); loop { let r = socket.write_all(b"Hello\n").await; if let Err(e) = r { info!("write error: {:?}", e); break; } Timer::after(Duration::from_secs(1)).await; } } }