working ethernet
This commit is contained in:
parent
ca0453df54
commit
dab73c3fec
|
@ -224,6 +224,35 @@ dependencies = [
|
||||||
"riscv",
|
"riscv",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "defmt"
|
||||||
|
version = "0.3.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d3a0ae7494d9bff013d7b89471f4c424356a71e9752e0c78abe7e6c608a16bb3"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags",
|
||||||
|
"defmt-macros",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "defmt-macros"
|
||||||
|
version = "0.3.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8500cbe4cca056412efce4215a63d0bc20492942aeee695f23b624a53e0a6854"
|
||||||
|
dependencies = [
|
||||||
|
"defmt-parser",
|
||||||
|
"proc-macro-error",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "defmt-parser"
|
||||||
|
version = "0.3.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0db23d29972d99baa3de2ee2ae3f104c10564a6d05a346eb3f4c4f2c0525a06e"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "embedded-dma"
|
name = "embedded-dma"
|
||||||
version = "0.2.0"
|
version = "0.2.0"
|
||||||
|
@ -342,6 +371,15 @@ dependencies = [
|
||||||
"stable_deref_trait",
|
"stable_deref_trait",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ieee802_3_miim"
|
||||||
|
version = "0.7.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fa6fe9a9feafccff3129a8ada9271d7f710a960be2b7c124583f7a3a5de3443e"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "indexmap"
|
name = "indexmap"
|
||||||
version = "1.9.1"
|
version = "1.9.1"
|
||||||
|
@ -363,6 +401,7 @@ dependencies = [
|
||||||
"cortex-m-rtic",
|
"cortex-m-rtic",
|
||||||
"cortex-m-semihosting 0.5.0",
|
"cortex-m-semihosting 0.5.0",
|
||||||
"fugit",
|
"fugit",
|
||||||
|
"ieee802_3_miim",
|
||||||
"log",
|
"log",
|
||||||
"nb 1.0.0",
|
"nb 1.0.0",
|
||||||
"num-traits",
|
"num-traits",
|
||||||
|
@ -384,9 +423,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.135"
|
version = "0.2.137"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "68783febc7782c6c5cb401fbda4de5a9898be1762314da0bb2c10ced61f18b0c"
|
checksum = "fc7fcc620a3bff7cdd7a365be3376c97191aeaccc2a603e600951e452615bf89"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libm"
|
name = "libm"
|
||||||
|
@ -666,11 +705,13 @@ checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "stm32-eth"
|
name = "stm32-eth"
|
||||||
version = "0.3.0"
|
version = "0.3.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "git+https://github.com/stm32-rs/stm32-eth#34243c92efbea19414fab27f34e282a2a4121190"
|
||||||
checksum = "09f6e20fd0f89dcf5637782090e654de814eecfb83c66ba41c2d64ce7f211b31"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aligned 0.4.1",
|
"aligned 0.4.1",
|
||||||
"cortex-m 0.7.6",
|
"cortex-m 0.7.6",
|
||||||
|
"defmt",
|
||||||
|
"ieee802_3_miim",
|
||||||
|
"smoltcp",
|
||||||
"stm32f4xx-hal",
|
"stm32f4xx-hal",
|
||||||
"volatile-register",
|
"volatile-register",
|
||||||
]
|
]
|
||||||
|
@ -714,9 +755,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "1.0.102"
|
version = "1.0.103"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3fcd952facd492f9be3ef0d0b7032a6e442ee9b361d4acc2b1d0c4aaa5f613a1"
|
checksum = "a864042229133ada95abf3b54fdc62ef5ccabe9515b64717bcb9a1919e59445d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
@ -747,14 +788,21 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "time"
|
name = "time"
|
||||||
version = "0.3.15"
|
version = "0.3.16"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d634a985c4d4238ec39cacaed2e7ae552fbd3c476b552c1deac3021b7d7eaf0c"
|
checksum = "0fab5c8b9980850e06d92ddbe3ab839c062c801f3927c0fb8abd6fc8e918fbca"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"num_threads",
|
"num_threads",
|
||||||
|
"time-core",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "time-core"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2e153e1f1acaef8acc537e68b44906d2db6436e2b35ac2c6b42640fff91f00fd"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "typenum"
|
name = "typenum"
|
||||||
version = "1.15.0"
|
version = "1.15.0"
|
||||||
|
|
|
@ -23,8 +23,9 @@ bare-metal = "1"
|
||||||
nb = "1"
|
nb = "1"
|
||||||
cortex-m-log = { version = "0.7.0", features = ["log-integration", "semihosting"] }
|
cortex-m-log = { version = "0.7.0", features = ["log-integration", "semihosting"] }
|
||||||
stm32f4xx-hal = { version = "0.13.2", features = ["rt", "stm32f407", "usb_fs", "rtic-monotonic"] }
|
stm32f4xx-hal = { version = "0.13.2", features = ["rt", "stm32f407", "usb_fs", "rtic-monotonic"] }
|
||||||
stm32-eth = { version = "0.3.0", features = ["stm32f407"] }
|
stm32-eth = { git = "https://github.com/stm32-rs/stm32-eth", features = ["stm32f407", "smoltcp-phy", "smoltcp"] }
|
||||||
smoltcp = { version = "0.8.0", default-features = false, features = ["proto-ipv4", "socket-tcp", "log", "medium-ethernet"] }
|
smoltcp = { version = "0.8.1", default-features = false, features = ["proto-ipv4", "socket-tcp", "log", "medium-ethernet"] }
|
||||||
|
ieee802_3_miim = "0.7.2"
|
||||||
num-traits = { version = "0.2.15", default-features = false, features = ["libm"] }
|
num-traits = { version = "0.2.15", default-features = false, features = ["libm"] }
|
||||||
usb-device = "0.2.9"
|
usb-device = "0.2.9"
|
||||||
usbd-serial = "0.1.1"
|
usbd-serial = "0.1.1"
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
use super::{gpio, usb, delay};
|
use super::{gpio, usb, delay};
|
||||||
use crate::laser_diode::current_sources::*;
|
use crate::laser_diode::current_sources::*;
|
||||||
|
use smoltcp::iface::{SocketHandle, Interface};
|
||||||
|
use stm32_eth::stm32::ETHERNET_DMA;
|
||||||
use systick_monotonic::Systick;
|
use systick_monotonic::Systick;
|
||||||
use fugit::ExtU32;
|
use fugit::ExtU32;
|
||||||
use log::info;
|
use log::info;
|
||||||
|
@ -9,13 +11,15 @@ use stm32f4xx_hal::{
|
||||||
time::MegaHertz,
|
time::MegaHertz,
|
||||||
watchdog::IndependentWatchdog,
|
watchdog::IndependentWatchdog,
|
||||||
};
|
};
|
||||||
|
use crate::network::network;
|
||||||
|
use crate::network::network::EthernetPeripherals;
|
||||||
|
|
||||||
#[cfg(not(feature = "semihosting"))]
|
#[cfg(not(feature = "semihosting"))]
|
||||||
const WATCHDOG_PERIOD: u32 = 1000;
|
const WATCHDOG_PERIOD: u32 = 1000;
|
||||||
#[cfg(feature = "semihosting")]
|
#[cfg(feature = "semihosting")]
|
||||||
const WATCHDOG_PERIOD: u32 = 30000;
|
const WATCHDOG_PERIOD: u32 = 30000;
|
||||||
|
|
||||||
pub fn bootup(mut core_perif: CorePeripherals, perif: Peripherals) -> (IndependentWatchdog, Systick<1000_u32>) {
|
pub fn bootup(mut core_perif: CorePeripherals, perif: Peripherals, server_storage: &'static mut network::ServerStorage) -> (IndependentWatchdog, Systick<1000_u32>, network::ServerHandle) {
|
||||||
core_perif.SCB.enable_icache();
|
core_perif.SCB.enable_icache();
|
||||||
core_perif.SCB.enable_dcache(&mut core_perif.CPUID);
|
core_perif.SCB.enable_dcache(&mut core_perif.CPUID);
|
||||||
|
|
||||||
|
@ -33,7 +37,7 @@ pub fn bootup(mut core_perif: CorePeripherals, perif: Peripherals) -> (Independe
|
||||||
let systick = Systick::new(core_perif.SYST, clocks.hclk().to_Hz());
|
let systick = Systick::new(core_perif.SYST, clocks.hclk().to_Hz());
|
||||||
let delay = delay::AsmDelay::new(clocks.sysclk().to_Hz());
|
let delay = delay::AsmDelay::new(clocks.sysclk().to_Hz());
|
||||||
|
|
||||||
let (_eth_pins, usb, current_source_phy) = gpio::setup(
|
let (eth_pins, usb, current_source_phy, mdio, mdc) = gpio::setup(
|
||||||
clocks,
|
clocks,
|
||||||
perif.GPIOA,
|
perif.GPIOA,
|
||||||
perif.GPIOB,
|
perif.GPIOB,
|
||||||
|
@ -46,6 +50,14 @@ pub fn bootup(mut core_perif: CorePeripherals, perif: Peripherals) -> (Independe
|
||||||
perif.OTG_FS_PWRCLK,
|
perif.OTG_FS_PWRCLK,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let ethernet = EthernetPeripherals {
|
||||||
|
dma: perif.ETHERNET_DMA,
|
||||||
|
mac: perif.ETHERNET_MAC,
|
||||||
|
mmc: perif.ETHERNET_MMC,
|
||||||
|
};
|
||||||
|
let server = network::ServerHandle::new(eth_pins, ethernet, clocks, server_storage, mdio, mdc);
|
||||||
|
// let (serverhandle, iface) = network::setup(eth_pins, ethernet, clocks);
|
||||||
|
|
||||||
usb::State::setup(usb);
|
usb::State::setup(usb);
|
||||||
|
|
||||||
let mut laser = CurrentSource {
|
let mut laser = CurrentSource {
|
||||||
|
@ -64,5 +76,5 @@ pub fn bootup(mut core_perif: CorePeripherals, perif: Peripherals) -> (Independe
|
||||||
|
|
||||||
info!("Kirdy setup complete");
|
info!("Kirdy setup complete");
|
||||||
|
|
||||||
(wd, systick)
|
(wd, systick, server)
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@ use crate::laser_diode::current_sources::*;
|
||||||
use fugit::RateExtU32;
|
use fugit::RateExtU32;
|
||||||
use stm32_eth::EthPins;
|
use stm32_eth::EthPins;
|
||||||
use stm32f4xx_hal::{
|
use stm32f4xx_hal::{
|
||||||
gpio::{gpioa::*, gpiob::*, gpioc::*, gpiog::*, GpioExt, Input},
|
gpio::{GpioExt, AF11, Speed, Alternate},
|
||||||
otg_fs::USB,
|
otg_fs::USB,
|
||||||
pac::{GPIOA, GPIOB, GPIOC, GPIOD, GPIOG, OTG_FS_DEVICE, OTG_FS_GLOBAL, OTG_FS_PWRCLK, SPI2},
|
pac::{GPIOA, GPIOB, GPIOC, GPIOD, GPIOG, OTG_FS_DEVICE, OTG_FS_GLOBAL, OTG_FS_PWRCLK, SPI2},
|
||||||
rcc::Clocks,
|
rcc::Clocks,
|
||||||
|
@ -10,8 +10,7 @@ use stm32f4xx_hal::{
|
||||||
spi::{NoMiso, Spi},
|
spi::{NoMiso, Spi},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub type EthernetPins =
|
use crate::network::network::EthernetPins;
|
||||||
EthPins<PA1<Input>, PA7<Input>, PB11<Input>, PG13<Input>, PB13<Input>, PC4<Input>, PC5<Input>>;
|
|
||||||
|
|
||||||
pub fn setup(
|
pub fn setup(
|
||||||
clocks: Clocks,
|
clocks: Clocks,
|
||||||
|
@ -28,6 +27,8 @@ pub fn setup(
|
||||||
EthernetPins,
|
EthernetPins,
|
||||||
USB,
|
USB,
|
||||||
CurrentSourcePhyConstruct<CurrentSourcePhyCh0>,
|
CurrentSourcePhyConstruct<CurrentSourcePhyCh0>,
|
||||||
|
stm32f4xx_hal::gpio::PA2<Alternate<11>>,
|
||||||
|
stm32f4xx_hal::gpio::PC1<Alternate<11>>
|
||||||
// photo_diode_phy,
|
// photo_diode_phy,
|
||||||
// thermostat_phy
|
// thermostat_phy
|
||||||
) {
|
) {
|
||||||
|
@ -50,12 +51,18 @@ pub fn setup(
|
||||||
ref_clk: gpioa.pa1,
|
ref_clk: gpioa.pa1,
|
||||||
crs: gpioa.pa7,
|
crs: gpioa.pa7,
|
||||||
tx_en: gpiob.pb11,
|
tx_en: gpiob.pb11,
|
||||||
tx_d0: gpiog.pg13,
|
tx_d0: gpiob.pb12,
|
||||||
tx_d1: gpiob.pb13,
|
tx_d1: gpiob.pb13,
|
||||||
rx_d0: gpioc.pc4,
|
rx_d0: gpioc.pc4,
|
||||||
rx_d1: gpioc.pc5,
|
rx_d1: gpioc.pc5,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let mut mdio = gpioa.pa2.into_alternate::<11>();
|
||||||
|
let mut mdc = gpioc.pc1.into_alternate::<11>();
|
||||||
|
mdio.set_speed(Speed::VeryHigh);
|
||||||
|
mdc.set_speed(Speed::VeryHigh);
|
||||||
|
|
||||||
|
|
||||||
let current_source_phy = CurrentSourcePhyConstruct {
|
let current_source_phy = CurrentSourcePhyConstruct {
|
||||||
max5719_spi: Spi::new(
|
max5719_spi: Spi::new(
|
||||||
spi2,
|
spi2,
|
||||||
|
@ -77,5 +84,5 @@ pub fn setup(
|
||||||
current_source_short: gpioa.pa4.into_push_pull_output(),
|
current_source_short: gpioa.pa4.into_push_pull_output(),
|
||||||
};
|
};
|
||||||
|
|
||||||
(eth_pins, usb, current_source_phy)
|
(eth_pins, usb, current_source_phy, mdio, mdc)
|
||||||
}
|
}
|
||||||
|
|
32
src/main.rs
32
src/main.rs
|
@ -4,6 +4,7 @@
|
||||||
use rtic::app;
|
use rtic::app;
|
||||||
mod device;
|
mod device;
|
||||||
mod laser_diode;
|
mod laser_diode;
|
||||||
|
mod network;
|
||||||
|
|
||||||
// If RTT is used, print panic info through RTT
|
// If RTT is used, print panic info through RTT
|
||||||
#[cfg(feature = "RTT")]
|
#[cfg(feature = "RTT")]
|
||||||
|
@ -22,14 +23,22 @@ fn panic(info: &PanicInfo) -> ! {
|
||||||
use panic_halt as _;
|
use panic_halt as _;
|
||||||
|
|
||||||
// #[entry]
|
// #[entry]
|
||||||
#[app(device = stm32f4xx_hal::pac, peripherals = true, dispatchers = [TIM8_CC])]
|
#[app(device = stm32f4xx_hal::pac, peripherals = true, dispatchers = [TIM8_CC, TIM8_BRK_TIM12])]
|
||||||
mod app {
|
mod app {
|
||||||
|
|
||||||
use log::info;
|
use log::info;
|
||||||
|
use stm32_eth::stm32::ETHERNET_DMA;
|
||||||
use systick_monotonic::Systick;
|
use systick_monotonic::Systick;
|
||||||
use fugit::ExtU32;
|
use fugit::ExtU32;
|
||||||
use stm32f4xx_hal::watchdog::IndependentWatchdog;
|
use stm32f4xx_hal::watchdog::IndependentWatchdog;
|
||||||
use crate::device::{boot::bootup, log_setup};
|
use crate::device::{boot::bootup, log_setup};
|
||||||
|
use smoltcp::iface::{SocketHandle, Interface};
|
||||||
|
use crate::network::network;
|
||||||
|
|
||||||
|
fn now_fn() -> smoltcp::time::Instant {
|
||||||
|
let time = monotonics::now().duration_since_epoch().to_millis();
|
||||||
|
smoltcp::time::Instant::from_millis(time as i64)
|
||||||
|
}
|
||||||
|
|
||||||
#[monotonic(binds = SysTick, default = true)]
|
#[monotonic(binds = SysTick, default = true)]
|
||||||
type SystickTimer = Systick<1000>;
|
type SystickTimer = Systick<1000>;
|
||||||
|
@ -42,31 +51,42 @@ mod app {
|
||||||
#[local]
|
#[local]
|
||||||
struct Local {
|
struct Local {
|
||||||
wd: IndependentWatchdog,
|
wd: IndependentWatchdog,
|
||||||
|
// server_storage: network::network::ServerStorage::new(),
|
||||||
|
server_handle: network::ServerHandle
|
||||||
}
|
}
|
||||||
|
|
||||||
#[init]
|
#[init( local = [server_storage: network::ServerStorage = network::ServerStorage::new()] )]
|
||||||
fn init(cx: init::Context) -> (Shared, Local, init::Monotonics) {
|
fn init(cx: init::Context) -> (Shared, Local, init::Monotonics) {
|
||||||
log_setup::init_log();
|
log_setup::init_log();
|
||||||
info!("Kirdy init");
|
info!("Kirdy init");
|
||||||
|
|
||||||
let core_perif = cx.core;
|
let core_perif = cx.core;
|
||||||
let perif = cx.device;
|
let perif = cx.device;
|
||||||
let (wd, systick) = bootup(core_perif, perif);
|
let server_storage = cx.local.server_storage;
|
||||||
|
let (wd, systick, server_handle) = bootup(core_perif, perif, server_storage);
|
||||||
|
|
||||||
wd_feed::spawn().unwrap();
|
wd_feed::spawn().unwrap();
|
||||||
|
// server_poll::spawn().unwrap();
|
||||||
(Shared {}, Local {wd}, init::Monotonics(systick))
|
(Shared {}, Local {wd, server_handle}, init::Monotonics(systick))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[task(priority = 5, local = [wd])]
|
#[task(priority = 5, local = [wd])]
|
||||||
fn wd_feed (cx: wd_feed::Context) {
|
fn wd_feed (cx: wd_feed::Context) {
|
||||||
let start = monotonics::now();
|
let start = monotonics::now();
|
||||||
let wd = cx.local.wd;
|
let wd = cx.local.wd;
|
||||||
info!("feed wd");
|
// info!("feed wd");
|
||||||
wd.feed();
|
wd.feed();
|
||||||
wd_feed::spawn_at(start + 10_u32.millis()).unwrap();
|
wd_feed::spawn_at(start + 10_u32.millis()).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[task(binds = ETH, priority = 2, local = [server_handle, data: [u8; 512] = [0u8; 512]])]
|
||||||
|
fn server_poll (cx: server_poll::Context) {
|
||||||
|
let data = cx.local.data;
|
||||||
|
let server_handle = cx.local.server_handle;
|
||||||
|
server_handle.poll(data);
|
||||||
|
// server_poll::spawn_at(start + 10_u32.millis()).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
#[idle]
|
#[idle]
|
||||||
fn idle(_: idle::Context) -> ! {
|
fn idle(_: idle::Context) -> ! {
|
||||||
loop {
|
loop {
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
pub mod network;
|
|
@ -0,0 +1,280 @@
|
||||||
|
use fugit::Instant;
|
||||||
|
use smoltcp::iface::{InterfaceBuilder, NeighborCache, SocketHandle, Interface, SocketStorage};
|
||||||
|
use smoltcp::socket::{TcpSocket, TcpSocketBuffer, self, Socket};
|
||||||
|
use smoltcp::storage::RingBuffer;
|
||||||
|
use smoltcp::wire::{EthernetAddress, IpAddress, IpCidr, Ipv4Address};
|
||||||
|
use stm32f4xx_hal::gpio::{gpioa::*, gpiob::*, gpioc::*, gpiog::*, Input};
|
||||||
|
use stm32_eth::{EthPins, TxDescriptor, RxDescriptor, EthernetMAC};
|
||||||
|
use stm32_eth::stm32::{ETHERNET_DMA, ETHERNET_MAC, ETHERNET_MMC};
|
||||||
|
use stm32_eth::RingEntry;
|
||||||
|
use stm32_eth::TxRingEntry;
|
||||||
|
use stm32_eth::RxRingEntry;
|
||||||
|
use stm32f4xx_hal::rcc::Clocks;
|
||||||
|
use smoltcp::iface::Neighbor;
|
||||||
|
use stm32_eth::*;
|
||||||
|
use log::{info, warn, debug};
|
||||||
|
use smoltcp::iface::Route;
|
||||||
|
use smoltcp::wire::Ipv4Cidr;
|
||||||
|
use stm32f4xx_hal::gpio::Alternate;
|
||||||
|
use smoltcp::{
|
||||||
|
iface::{self},
|
||||||
|
socket::{TcpState},
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
use crate::app::monotonics::{self, now};
|
||||||
|
|
||||||
|
|
||||||
|
pub type EthernetPins =
|
||||||
|
EthPins<PA1<Input>, PA7<Input>, PB11<Input>, PB12<Input>, PB13<Input>, PC4<Input>, PC5<Input>>;
|
||||||
|
|
||||||
|
pub type EthInterface = Interface<'static, &'static mut EthernetDMA<'static, 'static>>;
|
||||||
|
|
||||||
|
const IPV4_ADDR: (u8, u8, u8, u8) = (192, 168, 1, 132);
|
||||||
|
const ADDRESS: (IpAddress, u16) = (IpAddress::Ipv4(Ipv4Address::new(IPV4_ADDR.0, IPV4_ADDR.1,IPV4_ADDR.2,IPV4_ADDR.3)), 1337);
|
||||||
|
const MAC: [u8; 6] = [0x02,0x5f,0x25,0x37,0x93,0x0e];
|
||||||
|
pub struct EthernetPeripherals {
|
||||||
|
pub dma: ETHERNET_DMA,
|
||||||
|
pub mac: ETHERNET_MAC,
|
||||||
|
pub mmc: ETHERNET_MMC,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct ServerHandle {
|
||||||
|
// storage: &'static mut ServerStorage,
|
||||||
|
socket_handle: SocketHandle,
|
||||||
|
iface: EthInterface
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct ServerStorage {
|
||||||
|
rx_ring: [RxRingEntry; 8],
|
||||||
|
tx_ring: [TxRingEntry; 2],
|
||||||
|
storage: NetworkStorage,
|
||||||
|
dma: core::mem::MaybeUninit<EthernetDMA<'static, 'static>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ServerStorage {
|
||||||
|
pub const fn new() -> Self {
|
||||||
|
ServerStorage {
|
||||||
|
rx_ring: [RxRingEntry::new(),RxRingEntry::new(),RxRingEntry::new(),RxRingEntry::new(),RxRingEntry::new(),RxRingEntry::new(),RxRingEntry::new(),RxRingEntry::new()],
|
||||||
|
tx_ring: [TxRingEntry::new(),TxRingEntry::new()],
|
||||||
|
storage: NetworkStorage::new(),
|
||||||
|
dma: core::mem::MaybeUninit::uninit(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// All storage required for networking
|
||||||
|
pub struct NetworkStorage {
|
||||||
|
pub ip_addrs: [IpCidr; 1],
|
||||||
|
pub sockets: [SocketStorage<'static>; 1],
|
||||||
|
pub tcp_socket_storage: TcpSocketStorage,
|
||||||
|
pub neighbor_cache: [Option<(IpAddress, Neighbor)>; 8],
|
||||||
|
pub routes_cache: [Option<(IpCidr, Route)>; 8],
|
||||||
|
}
|
||||||
|
|
||||||
|
impl NetworkStorage {
|
||||||
|
const IP_INIT: IpCidr =
|
||||||
|
IpCidr::Ipv4(Ipv4Cidr::new(Ipv4Address::new(IPV4_ADDR.0, IPV4_ADDR.1,IPV4_ADDR.2,IPV4_ADDR.3), 24));
|
||||||
|
|
||||||
|
pub const fn new() -> Self {
|
||||||
|
NetworkStorage {
|
||||||
|
ip_addrs: [Self::IP_INIT],
|
||||||
|
neighbor_cache: [None; 8],
|
||||||
|
routes_cache: [None; 8],
|
||||||
|
sockets: [SocketStorage::EMPTY; 1],
|
||||||
|
tcp_socket_storage: TcpSocketStorage::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Storage of TCP sockets
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
pub struct TcpSocketStorage {
|
||||||
|
rx_storage: [u8; 2048],
|
||||||
|
tx_storage: [u8; 2048],
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TcpSocketStorage {
|
||||||
|
const fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
rx_storage: [0; 2048],
|
||||||
|
tx_storage: [0; 2048],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn now_fn() -> smoltcp::time::Instant {
|
||||||
|
let time = monotonics::now().duration_since_epoch().to_millis();
|
||||||
|
smoltcp::time::Instant::from_millis(time as i64)
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ServerHandle {
|
||||||
|
|
||||||
|
pub fn new(
|
||||||
|
eth_pins: EthernetPins,
|
||||||
|
ethernet: EthernetPeripherals,
|
||||||
|
clocks: Clocks,
|
||||||
|
storage: &'static mut ServerStorage,
|
||||||
|
mdio: stm32f4xx_hal::gpio::PA2<Alternate<11>>,
|
||||||
|
mdc: stm32f4xx_hal::gpio::PC1<Alternate<11>>
|
||||||
|
) -> ServerHandle {
|
||||||
|
|
||||||
|
let (dma, mac) = stm32_eth::new_with_mii(
|
||||||
|
ethernet.mac,
|
||||||
|
ethernet.mmc,
|
||||||
|
ethernet.dma,
|
||||||
|
&mut storage.rx_ring[..],
|
||||||
|
&mut storage.tx_ring[..],
|
||||||
|
clocks,
|
||||||
|
eth_pins,
|
||||||
|
mdio,
|
||||||
|
mdc
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let mut routes = smoltcp::iface::Routes::new(&mut storage.storage.routes_cache[..]);
|
||||||
|
routes
|
||||||
|
.add_default_ipv4_route(Ipv4Address::new(192, 168, 1, 1))
|
||||||
|
.ok();
|
||||||
|
|
||||||
|
|
||||||
|
let dma = storage.dma.write(dma);
|
||||||
|
dma.enable_interrupt();
|
||||||
|
|
||||||
|
let rx_buffer = TcpSocketBuffer::new(&mut storage.storage.tcp_socket_storage.rx_storage[..]);
|
||||||
|
let tx_buffer = TcpSocketBuffer::new(&mut storage.storage.tcp_socket_storage.tx_storage[..]);
|
||||||
|
let socket = TcpSocket::new(rx_buffer, tx_buffer);
|
||||||
|
|
||||||
|
let mut iface = InterfaceBuilder::new(dma, &mut storage.storage.sockets[..])
|
||||||
|
.hardware_addr(EthernetAddress(MAC).into())
|
||||||
|
.ip_addrs(&mut storage.storage.ip_addrs[..])
|
||||||
|
.neighbor_cache(NeighborCache::new(&mut storage.storage.neighbor_cache[..]))
|
||||||
|
.routes(routes)
|
||||||
|
.finalize();
|
||||||
|
let mut server = ServerHandle {
|
||||||
|
socket_handle: iface.add_socket(socket),
|
||||||
|
iface: iface
|
||||||
|
};
|
||||||
|
let socket = server.iface.get_socket::<TcpSocket>(server.socket_handle);
|
||||||
|
socket.listen(ADDRESS).ok();
|
||||||
|
server.iface.poll(now_fn());
|
||||||
|
if let Ok(mut phy) = EthernetPhy::from_miim(mac, 0) {
|
||||||
|
info!(
|
||||||
|
"Resetting PHY as an extra step. Type: {}",
|
||||||
|
phy.ident_string()
|
||||||
|
);
|
||||||
|
|
||||||
|
phy.phy_init();
|
||||||
|
} else {
|
||||||
|
info!("Not resetting unsupported PHY.");
|
||||||
|
}
|
||||||
|
|
||||||
|
server
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn poll(&mut self, buffer: &mut [u8]) {
|
||||||
|
|
||||||
|
// info!("poll eth");
|
||||||
|
let interrupt_reason = self.iface.device_mut().interrupt_handler();
|
||||||
|
// debug!("Reason: {:?}", interrupt_reason);
|
||||||
|
|
||||||
|
self.iface.poll(now_fn()).ok();
|
||||||
|
|
||||||
|
let socket = self.iface.get_socket::<TcpSocket>(self.socket_handle);
|
||||||
|
if let Ok(recv_bytes) = socket.recv_slice(buffer) {
|
||||||
|
if recv_bytes > 0 {
|
||||||
|
socket.send_slice(&buffer[..recv_bytes]).ok();
|
||||||
|
info!("Echoed {} bytes.", recv_bytes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !socket.is_listening() && !socket.is_open() || socket.state() == TcpState::CloseWait {
|
||||||
|
socket.abort();
|
||||||
|
socket.listen(ADDRESS).ok();
|
||||||
|
warn!("Disconnected... Reopening listening socket.");
|
||||||
|
}
|
||||||
|
|
||||||
|
self.iface.poll(now_fn()).ok();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
use ieee802_3_miim::{
|
||||||
|
phy::{
|
||||||
|
lan87xxa::{LAN8720A, LAN8742A},
|
||||||
|
BarePhy, KSZ8081R,
|
||||||
|
},
|
||||||
|
Miim, Pause, Phy,
|
||||||
|
};
|
||||||
|
|
||||||
|
/// An ethernet PHY
|
||||||
|
pub enum EthernetPhy<M: Miim> {
|
||||||
|
/// LAN8720A
|
||||||
|
LAN8720A(LAN8720A<M>),
|
||||||
|
/// LAN8742A
|
||||||
|
LAN8742A(LAN8742A<M>),
|
||||||
|
/// KSZ8081R
|
||||||
|
KSZ8081R(KSZ8081R<M>),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<M: Miim> Phy<M> for EthernetPhy<M> {
|
||||||
|
fn best_supported_advertisement(&self) -> ieee802_3_miim::AutoNegotiationAdvertisement {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_miim(&mut self) -> &mut M {
|
||||||
|
match self {
|
||||||
|
EthernetPhy::LAN8720A(phy) => phy.get_miim(),
|
||||||
|
EthernetPhy::LAN8742A(phy) => phy.get_miim(),
|
||||||
|
EthernetPhy::KSZ8081R(phy) => phy.get_miim(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_phy_addr(&self) -> u8 {
|
||||||
|
match self {
|
||||||
|
EthernetPhy::LAN8720A(phy) => phy.get_phy_addr(),
|
||||||
|
EthernetPhy::LAN8742A(phy) => phy.get_phy_addr(),
|
||||||
|
EthernetPhy::KSZ8081R(phy) => phy.get_phy_addr(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<M: Miim> EthernetPhy<M> {
|
||||||
|
/// Attempt to create one of the known PHYs from the given
|
||||||
|
/// MIIM.
|
||||||
|
///
|
||||||
|
/// Returns an error if the PHY does not support the extended register
|
||||||
|
/// set, or if the PHY's identifier does not correspond to a known PHY.
|
||||||
|
pub fn from_miim(miim: M, phy_addr: u8) -> Result<Self, ()> {
|
||||||
|
let mut bare = BarePhy::new(miim, phy_addr, Pause::NoPause);
|
||||||
|
let phy_ident = bare.phy_ident().ok_or(())?;
|
||||||
|
let miim = bare.release();
|
||||||
|
match phy_ident & 0xFFFFFFF0 {
|
||||||
|
0x0007C0F0 => Ok(Self::LAN8720A(LAN8720A::new(miim, phy_addr))),
|
||||||
|
0x0007C130 => Ok(Self::LAN8742A(LAN8742A::new(miim, phy_addr))),
|
||||||
|
0x00221560 => Ok(Self::KSZ8081R(KSZ8081R::new(miim, phy_addr))),
|
||||||
|
_ => Err(()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get a string describing the type of PHY
|
||||||
|
pub const fn ident_string(&self) -> &'static str {
|
||||||
|
match self {
|
||||||
|
EthernetPhy::LAN8720A(_) => "LAN8720A",
|
||||||
|
EthernetPhy::LAN8742A(_) => "LAN8742A",
|
||||||
|
EthernetPhy::KSZ8081R(_) => "KSZ8081R",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Initialize the PHY
|
||||||
|
pub fn phy_init(&mut self) {
|
||||||
|
match self {
|
||||||
|
EthernetPhy::LAN8720A(phy) => phy.phy_init(),
|
||||||
|
EthernetPhy::LAN8742A(phy) => phy.phy_init(),
|
||||||
|
EthernetPhy::KSZ8081R(phy) => {
|
||||||
|
phy.set_autonegotiation_advertisement(phy.best_supported_advertisement());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue