#![no_std] #![no_main] use defmt::*; use embassy_executor::Spawner; use embassy_net::udp::{PacketMetadata, UdpSocket}; use embassy_net::{Ipv4Address, Ipv4Cidr, StackResources}; use embassy_stm32::eth::{Ethernet, GenericPhy, PacketQueue}; use embassy_stm32::peripherals::ETH; use embassy_stm32::rng::Rng; use embassy_stm32::{bind_interrupts, eth, peripherals, rng, Config}; use embassy_time::Timer; use heapless::Vec; use static_cell::StaticCell; use {defmt_rtt as _, panic_probe as _}; bind_interrupts!(struct Irqs { ETH => eth::InterruptHandler; RNG => rng::InterruptHandler; }); type Device = Ethernet<'static, ETH, GenericPhy>; #[embassy_executor::task] async fn net_task(mut runner: embassy_net::Runner<'static, Device>) -> ! { runner.run().await } #[embassy_executor::main] async fn main(spawner: Spawner) -> ! { let mut config = Config::default(); { use embassy_stm32::rcc::*; config.rcc.hsi = Some(HSIPrescaler::DIV1); config.rcc.csi = true; config.rcc.hsi48 = Some(Default::default()); // needed for RNG config.rcc.pll1 = Some(Pll { source: PllSource::HSI, prediv: PllPreDiv::DIV4, mul: PllMul::MUL50, divp: Some(PllDiv::DIV2), divq: None, divr: None, }); config.rcc.sys = Sysclk::PLL1_P; // 400 Mhz config.rcc.ahb_pre = AHBPrescaler::DIV2; // 200 Mhz config.rcc.apb1_pre = APBPrescaler::DIV2; // 100 Mhz config.rcc.apb2_pre = APBPrescaler::DIV2; // 100 Mhz config.rcc.apb4_pre = APBPrescaler::DIV2; // 100 Mhz config.rcc.apb5_pre = APBPrescaler::DIV2; // 100 Mhz config.rcc.voltage_scale = VoltageScale::HIGH; } 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]; static PACKETS: StaticCell> = StaticCell::new(); let device = Ethernet::new( PACKETS.init(PacketQueue::<4, 4>::new()), p.ETH, Irqs, p.PB6, p.PA2, p.PG6, p.PA7, p.PG4, p.PG5, p.PG13, p.PG12, p.PG11, GenericPhy::new(0), mac_addr, ); // Have to use UDP w/ static config to fit in internal flash // 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 static RESOURCES: StaticCell> = StaticCell::new(); let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed); // Launch network task unwrap!(spawner.spawn(net_task(runner))); // 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_meta = [PacketMetadata::EMPTY; 16]; let mut rx_buffer = [0; 1024]; let mut tx_meta = [PacketMetadata::EMPTY; 16]; let mut tx_buffer = [0; 1024]; let remote_endpoint = (Ipv4Address::new(10, 42, 0, 1), 8000); let socket = UdpSocket::new(stack, &mut rx_meta, &mut rx_buffer, &mut tx_meta, &mut tx_buffer); loop { // You need to start a server on the host machine, for example: `nc -lu 8000` socket .send_to(b"Hello, world", remote_endpoint) .await .expect("Buffer sent"); Timer::after_secs(1).await; } }