diff options
| author | dvdsk <[email protected]> | 2024-06-07 23:46:59 +0200 |
|---|---|---|
| committer | dvdsk <[email protected]> | 2024-06-07 23:46:59 +0200 |
| commit | 1812ccd276a6c277e7c99191c0aa5ce3d1c90e84 (patch) | |
| tree | 14187edbb0859b1352eff648547e1ea3ea7de131 | |
| parent | 72c2b06520a2e25e180df6d89d5b3b39a8380f0c (diff) | |
Adds an example for using the w5500 with an stm32f4
This example takes into account the lower memory on the stm32f4. That
should prevent anyone wanting to use the w5500 on any stm from adapting
the w5500 example for the rp which uses a lot more RAM.
| -rw-r--r-- | examples/stm32f4/Cargo.toml | 2 | ||||
| -rw-r--r-- | examples/stm32f4/src/bin/eth_w5500.rs | 139 |
2 files changed, 141 insertions, 0 deletions
diff --git a/examples/stm32f4/Cargo.toml b/examples/stm32f4/Cargo.toml index 52b7ce9e8..11cb4cb3c 100644 --- a/examples/stm32f4/Cargo.toml +++ b/examples/stm32f4/Cargo.toml | |||
| @@ -12,6 +12,7 @@ embassy-executor = { version = "0.5.0", path = "../../embassy-executor", feature | |||
| 12 | embassy-time = { version = "0.3.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } | 12 | embassy-time = { version = "0.3.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } |
| 13 | embassy-usb = { version = "0.2.0", path = "../../embassy-usb", features = ["defmt" ] } | 13 | embassy-usb = { version = "0.2.0", path = "../../embassy-usb", features = ["defmt" ] } |
| 14 | embassy-net = { version = "0.4.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", ] } | 14 | embassy-net = { version = "0.4.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", ] } |
| 15 | embassy-net-wiznet = { version = "0.1.0", path = "../../embassy-net-wiznet", features = ["defmt"] } | ||
| 15 | embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } | 16 | embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } |
| 16 | 17 | ||
| 17 | defmt = "0.3" | 18 | defmt = "0.3" |
| @@ -20,6 +21,7 @@ defmt-rtt = "0.4" | |||
| 20 | cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } | 21 | cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } |
| 21 | cortex-m-rt = "0.7.0" | 22 | cortex-m-rt = "0.7.0" |
| 22 | embedded-hal = "0.2.6" | 23 | embedded-hal = "0.2.6" |
| 24 | embedded-hal-bus = { version = "0.2", features = ["async"] } | ||
| 23 | embedded-io = { version = "0.6.0" } | 25 | embedded-io = { version = "0.6.0" } |
| 24 | embedded-io-async = { version = "0.6.1" } | 26 | embedded-io-async = { version = "0.6.1" } |
| 25 | panic-probe = { version = "0.3", features = ["print-defmt"] } | 27 | panic-probe = { version = "0.3", features = ["print-defmt"] } |
diff --git a/examples/stm32f4/src/bin/eth_w5500.rs b/examples/stm32f4/src/bin/eth_w5500.rs new file mode 100644 index 000000000..827e74c51 --- /dev/null +++ b/examples/stm32f4/src/bin/eth_w5500.rs | |||
| @@ -0,0 +1,139 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | |||
| 4 | use defmt::*; | ||
| 5 | use embassy_executor::Spawner; | ||
| 6 | use embassy_net::tcp::TcpSocket; | ||
| 7 | use embassy_net::{Ipv4Address, Stack, StackResources}; | ||
| 8 | use embassy_net_wiznet::{chip::W5500, Device, Runner, State}; | ||
| 9 | use embassy_stm32::gpio::{Level, Output, Pull, Speed}; | ||
| 10 | use embassy_stm32::exti::ExtiInput; | ||
| 11 | use embassy_stm32::rng::Rng; | ||
| 12 | use embassy_stm32::spi::Spi; | ||
| 13 | use embassy_stm32::mode::Async; | ||
| 14 | use embassy_stm32::time::Hertz; | ||
| 15 | use embassy_stm32::{bind_interrupts, peripherals, rng, spi, Config}; | ||
| 16 | use embassy_time::{Timer, Delay}; | ||
| 17 | use embedded_io_async::Write; | ||
| 18 | use embedded_hal_bus::spi::ExclusiveDevice; | ||
| 19 | use static_cell::StaticCell; | ||
| 20 | use {defmt_rtt as _, panic_probe as _}; | ||
| 21 | |||
| 22 | bind_interrupts!(struct Irqs { | ||
| 23 | HASH_RNG => rng::InterruptHandler<peripherals::RNG>; | ||
| 24 | }); | ||
| 25 | |||
| 26 | type EthernetSPI = ExclusiveDevice<Spi<'static, Async>, Output<'static>, Delay>; | ||
| 27 | #[embassy_executor::task] | ||
| 28 | async fn ethernet_task( | ||
| 29 | runner: Runner<'static, W5500, EthernetSPI, ExtiInput<'static>, Output<'static>>, | ||
| 30 | ) -> ! { | ||
| 31 | runner.run().await | ||
| 32 | } | ||
| 33 | |||
| 34 | #[embassy_executor::task] | ||
| 35 | async fn net_task(stack: &'static Stack<Device<'static>>) -> ! { | ||
| 36 | stack.run().await | ||
| 37 | } | ||
| 38 | |||
| 39 | #[embassy_executor::main] | ||
| 40 | async fn main(spawner: Spawner) -> ! { | ||
| 41 | let mut config = Config::default(); | ||
| 42 | { | ||
| 43 | use embassy_stm32::rcc::*; | ||
| 44 | config.rcc.hse = Some(Hse { | ||
| 45 | freq: Hertz(8_000_000), | ||
| 46 | mode: HseMode::Bypass, | ||
| 47 | }); | ||
| 48 | config.rcc.pll_src = PllSource::HSE; | ||
| 49 | config.rcc.pll = Some(Pll { | ||
| 50 | prediv: PllPreDiv::DIV4, | ||
| 51 | mul: PllMul::MUL180, | ||
| 52 | divp: Some(PllPDiv::DIV2), // 8mhz / 4 * 180 / 2 = 180Mhz. | ||
| 53 | divq: None, | ||
| 54 | divr: None, | ||
| 55 | }); | ||
| 56 | config.rcc.ahb_pre = AHBPrescaler::DIV1; | ||
| 57 | config.rcc.apb1_pre = APBPrescaler::DIV4; | ||
| 58 | config.rcc.apb2_pre = APBPrescaler::DIV2; | ||
| 59 | config.rcc.sys = Sysclk::PLL1_P; | ||
| 60 | } | ||
| 61 | let p = embassy_stm32::init(config); | ||
| 62 | |||
| 63 | info!("Hello World!"); | ||
| 64 | |||
| 65 | // Generate random seed | ||
| 66 | let mut rng = Rng::new(p.RNG, Irqs); | ||
| 67 | let mut seed = [0; 8]; | ||
| 68 | unwrap!(rng.async_fill_bytes(&mut seed).await); | ||
| 69 | let seed = u64::from_le_bytes(seed); | ||
| 70 | |||
| 71 | let mut spi_cfg = spi::Config::default(); | ||
| 72 | spi_cfg.frequency = Hertz(50_000_000); // up to 50m works | ||
| 73 | let (miso, mosi, clk) = (p.PA6, p.PA7, p.PA5); | ||
| 74 | let spi = Spi::new(p.SPI1, clk, mosi, miso, p.DMA2_CH3, p.DMA2_CH0, spi_cfg); | ||
| 75 | let cs = Output::new(p.PA4, Level::High, Speed::VeryHigh); | ||
| 76 | let spi = unwrap!(ExclusiveDevice::new(spi, cs, Delay)); | ||
| 77 | |||
| 78 | let w5500_int = ExtiInput::new(p.PB0, p.EXTI0, Pull::Up); | ||
| 79 | let w5500_reset = Output::new(p.PB1, Level::High, Speed::VeryHigh); | ||
| 80 | |||
| 81 | let mac_addr = [0x02, 234, 3, 4, 82, 231]; | ||
| 82 | static STATE: StaticCell<State<2, 2>> = StaticCell::new(); | ||
| 83 | let state = STATE.init(State::<2, 2>::new()); | ||
| 84 | let (device, runner) = embassy_net_wiznet::new(mac_addr, state, spi, w5500_int, w5500_reset).await; | ||
| 85 | unwrap!(spawner.spawn(ethernet_task(runner))); | ||
| 86 | |||
| 87 | let config = embassy_net::Config::dhcpv4(Default::default()); | ||
| 88 | //let config = embassy_net::Config::ipv4_static(embassy_net::StaticConfigV4 { | ||
| 89 | // address: Ipv4Cidr::new(Ipv4Address::new(10, 42, 0, 61), 24), | ||
| 90 | // dns_servers: Vec::new(), | ||
| 91 | // gateway: Some(Ipv4Address::new(10, 42, 0, 1)), | ||
| 92 | //}); | ||
| 93 | |||
| 94 | static STACK: StaticCell<Stack<Device>> = StaticCell::new(); | ||
| 95 | static RESOURCES: StaticCell<StackResources<2>> = StaticCell::new(); | ||
| 96 | let stack = &*STACK.init(Stack::new( | ||
| 97 | device, | ||
| 98 | config, | ||
| 99 | RESOURCES.init(StackResources::<2>::new()), | ||
| 100 | seed, | ||
| 101 | )); | ||
| 102 | |||
| 103 | // Launch network task | ||
| 104 | unwrap!(spawner.spawn(net_task(stack))); | ||
| 105 | |||
| 106 | // Ensure DHCP configuration is up before trying connect | ||
| 107 | stack.wait_config_up().await; | ||
| 108 | |||
| 109 | info!("Network task initialized"); | ||
| 110 | |||
| 111 | // Then we can use it! | ||
| 112 | let mut rx_buffer = [0; 1024]; | ||
| 113 | let mut tx_buffer = [0; 1024]; | ||
| 114 | |||
| 115 | loop { | ||
| 116 | let mut socket = TcpSocket::new(stack, &mut rx_buffer, &mut tx_buffer); | ||
| 117 | |||
| 118 | socket.set_timeout(Some(embassy_time::Duration::from_secs(10))); | ||
| 119 | |||
| 120 | let remote_endpoint = (Ipv4Address::new(10, 42, 0, 1), 8000); | ||
| 121 | info!("connecting..."); | ||
| 122 | let r = socket.connect(remote_endpoint).await; | ||
| 123 | if let Err(e) = r { | ||
| 124 | info!("connect error: {:?}", e); | ||
| 125 | Timer::after_secs(1).await; | ||
| 126 | continue; | ||
| 127 | } | ||
| 128 | info!("connected!"); | ||
| 129 | let buf = [0; 1024]; | ||
| 130 | loop { | ||
| 131 | let r = socket.write_all(&buf).await; | ||
| 132 | if let Err(e) = r { | ||
| 133 | info!("write error: {:?}", e); | ||
| 134 | break; | ||
| 135 | } | ||
| 136 | Timer::after_secs(1).await; | ||
| 137 | } | ||
| 138 | } | ||
| 139 | } | ||
