#![no_main] #![no_std] //extern crate cortex_m_rt as rt; use core::sync::atomic::{AtomicU32, Ordering}; //#[macro_use] //extern crate log; //extern crate cortex_m use panic_semihosting as _; use cortex_m; use cortex_m::asm::nop; use cortex_m_rt::{ entry, exception, }; use cortex_m_semihosting::hprintln; extern crate smoltcp; extern crate stm32h7_ethernet as ethernet; use stm32h7xx_hal::gpio::Speed; use stm32h7xx_hal::hal::digital::v2::OutputPin; use stm32h7xx_hal::rcc::CoreClocks; use stm32h7xx_hal::{pac, prelude::*, stm32, stm32::interrupt}; use Speed::*; /* #[cfg(feature = "itm")] use cortex_m_log::log::{trick_init, Logger}; #[cfg(feature = "itm")] use cortex_m_log::{ destination::Itm, printer::itm::InterruptSync as InterruptSyncItm, }; */ use core::{ str, fmt::Write }; use core::mem::uninitialized; // Exception: no phy::wait //use smoltcp::phy::wait as phy_wait; use smoltcp::wire::{EthernetAddress, IpAddress, IpCidr}; use smoltcp::iface::{NeighborCache, EthernetInterfaceBuilder}; use smoltcp::socket::SocketSet; //use smoltcp::socket::{UdpSocket, UdpSocketBuffer, UdpPacketMetadata}; use smoltcp::socket::{SocketHandle, TcpSocket, TcpSocketBuffer}; use smoltcp::time::{Duration, Instant}; /// Configure SYSTICK for 1ms timebase fn systick_init(syst: &mut stm32::SYST, clocks: CoreClocks) { let c_ck_mhz = clocks.c_ck().0 / 1_000_000; let syst_calib = 0x3E8; syst.set_clock_source(cortex_m::peripheral::syst::SystClkSource::Core); syst.set_reload((syst_calib * c_ck_mhz) - 1); syst.enable_interrupt(); syst.enable_counter(); } /// ====================================================================== /// Entry point /// ====================================================================== /// TIME is an atomic u32 that counts milliseconds. Although not used /// here, it is very useful to have for network protocols static TIME: AtomicU32 = AtomicU32::new(0); /// Locally administered MAC address const MAC_ADDRESS: [u8; 6] = [0x02, 0x00, 0x11, 0x22, 0x33, 0x44]; /// Ethernet descriptor rings are a global singleton #[link_section = ".sram3.eth"] static mut DES_RING: ethernet::DesRing = ethernet::DesRing::new(); // Theoratical maximum number of socket that can be handled const SOCKET_COUNT: usize = 2; // Give buffer sizes of transmitting and receiving TCP packets const TCP_RX_BUFFER_SIZE: usize = 2048; const TCP_TX_BUFFER_SIZE: usize = 2048; // the program entry point #[entry] fn main() -> ! { let mut cp = cortex_m::Peripherals::take().unwrap(); let dp = pac::Peripherals::take().unwrap(); // Initialise power... let pwr = dp.PWR.constrain(); let vos = pwr.freeze(); // Initialise SRAM3 dp.RCC.ahb2enr.modify(|_, w| w.sram3en().set_bit()); // Initialise clocks... let rcc = dp.RCC.constrain(); let ccdr = rcc .sys_ck(200.mhz()) .hclk(200.mhz()) .pll1_r_ck(100.mhz()) // for TRACECK .freeze(vos, &dp.SYSCFG); // Get the delay provider. let delay = cp.SYST.delay(ccdr.clocks); // Initialise system... cp.SCB.invalidate_icache(); cp.SCB.enable_icache(); // TODO: ETH DMA coherence issues // cp.SCB.enable_dcache(&mut cp.CPUID); cp.DWT.enable_cycle_counter(); // Initialise IO... let gpioa = dp.GPIOA.split(ccdr.peripheral.GPIOA); let gpiob = dp.GPIOB.split(ccdr.peripheral.GPIOB); let gpioc = dp.GPIOC.split(ccdr.peripheral.GPIOC); let gpioe = dp.GPIOE.split(ccdr.peripheral.GPIOE); let gpiog = dp.GPIOG.split(ccdr.peripheral.GPIOG); let mut link_led = gpiob.pb0.into_push_pull_output(); // LED1, green let mut status_led = gpioe.pe1.into_push_pull_output(); // LD2, yellow let mut listen_led = gpiob.pb14.into_push_pull_output(); // LD3, red link_led.set_low().ok(); status_led.set_low().ok(); listen_led.set_low().ok(); let _rmii_ref_clk = gpioa.pa1.into_alternate_af11().set_speed(VeryHigh); let _rmii_mdio = gpioa.pa2.into_alternate_af11().set_speed(VeryHigh); let _rmii_mdc = gpioc.pc1.into_alternate_af11().set_speed(VeryHigh); let _rmii_crs_dv = gpioa.pa7.into_alternate_af11().set_speed(VeryHigh); let _rmii_rxd0 = gpioc.pc4.into_alternate_af11().set_speed(VeryHigh); let _rmii_rxd1 = gpioc.pc5.into_alternate_af11().set_speed(VeryHigh); let _rmii_tx_en = gpiog.pg11.into_alternate_af11().set_speed(VeryHigh); let _rmii_txd0 = gpiog.pg13.into_alternate_af11().set_speed(VeryHigh); let _rmii_txd1 = gpiob.pb13.into_alternate_af11().set_speed(VeryHigh); // Initialise ethernet... assert_eq!(ccdr.clocks.hclk().0, 200_000_000); // HCLK 200MHz assert_eq!(ccdr.clocks.pclk1().0, 100_000_000); // PCLK 100MHz assert_eq!(ccdr.clocks.pclk2().0, 100_000_000); // PCLK 100MHz assert_eq!(ccdr.clocks.pclk4().0, 100_000_000); // PCLK 100MHz let mac_addr = smoltcp::wire::EthernetAddress::from_bytes(&MAC_ADDRESS); let (_eth_dma, mut eth_mac) = unsafe { ethernet::ethernet_init( dp.ETHERNET_MAC, dp.ETHERNET_MTL, dp.ETHERNET_DMA, &mut DES_RING, mac_addr.clone(), ) }; unsafe { ethernet::enable_interrupt(); cp.NVIC.set_priority(stm32::Interrupt::ETH, 196); // Mid prio cortex_m::peripheral::NVIC::unmask(stm32::Interrupt::ETH); } // ---------------------------------------------------------- // Begin periodic tasks systick_init(&mut delay.free(), ccdr.clocks); unsafe { cp.SCB.shpr[15 - 4].write(128); } // systick exception priority // ---------------------------------------------------------- // Main application loop // Setup addresses, maybe not MAC? // MAC is set up in prior let local_addr = IpAddress::v4(192, 168, 1, 200); let mut ip_addrs = [IpCidr::new(local_addr, 24)]; // let neighbor_cache = NeighborCache::new(BTreeMap::new()); let mut neighbor_storage = [None; 16]; let neighbor_cache = NeighborCache::new(&mut neighbor_storage[..]); // Device? _eth_dma, as it implements phy::device let mut iface = EthernetInterfaceBuilder::new(_eth_dma) .ethernet_addr(mac_addr) .neighbor_cache(neighbor_cache) .ip_addrs(&mut ip_addrs[..]) .finalize(); // TODO: Need Iinitialize TCP socket storage? // Yes cannot into vectors let mut rx_storage = [0; TCP_RX_BUFFER_SIZE]; let mut tx_storage = [0; TCP_TX_BUFFER_SIZE]; // Setup TCP sockets let tcp1_rx_buffer = TcpSocketBuffer::new(&mut rx_storage[..]); let tcp1_tx_buffer = TcpSocketBuffer::new(&mut tx_storage[..]); let mut tcp1_socket = TcpSocket::new(tcp1_rx_buffer, tcp1_tx_buffer); // Setup a silent socket let mut silent_rx_storage = [0; TCP_RX_BUFFER_SIZE]; let mut silent_tx_storage = [0; TCP_TX_BUFFER_SIZE]; let silent_rx_buffer = TcpSocketBuffer::new(&mut silent_rx_storage[..]); let silent_tx_buffer = TcpSocketBuffer::new(&mut silent_tx_storage[..]); let mut silent_socket = TcpSocket::new(silent_rx_buffer, silent_tx_buffer); // Socket storage let mut sockets_storage = [ None, None ]; let mut sockets = SocketSet::new(&mut sockets_storage[..]); let tcp1_handle = sockets.add(tcp1_socket); let silent_handle = sockets.add(silent_socket); let mut handles: [SocketHandle; SOCKET_COUNT] = unsafe { uninitialized() }; let mut eth_up = false; let mut receive_and_not_send = true; let mut counter = 0; // Record activeness of silent socket, init as false let mut silent_socket_active = false; loop { let _time = TIME.load(Ordering::Relaxed); let eth_last = eth_up; match iface.poll(&mut sockets, Instant::from_millis(_time as i64)) { Ok(_) => { eth_up = true; link_led.set_high().unwrap(); }, Err(e) => { eth_up = false; link_led.set_low().unwrap(); }, }; // Counting socket (:6969) { let mut socket = sockets.get::(tcp1_handle); if !socket.is_open() { socket.listen(6969).unwrap(); socket.set_timeout(Some(Duration::from_millis(5000))); } match socket.is_listening() { false => listen_led.set_low().unwrap(), _ => listen_led.set_high().unwrap(), }; match socket.is_active() { true => status_led.set_high().unwrap(), _ => status_led.set_low().unwrap(), }; if socket.can_recv() && receive_and_not_send { hprintln!("recv 6969"); let data = socket.recv(|buffer| { counter += buffer.len(); (buffer.len(), buffer) }); hprintln!("{:?}", data); receive_and_not_send = false; } else if socket.can_recv() { hprintln!("{:?}", socket.can_recv()); } if socket.can_send() && !receive_and_not_send { writeln!(socket, "{}", counter); receive_and_not_send = true; } } // Silent socket (:7000) { let mut socket = sockets.get::(silent_handle); if !socket.is_open() { socket.listen(7000).unwrap(); socket.set_timeout(Some(Duration::from_millis(1000000))); } if socket.is_active() && !silent_socket_active { hprintln!("tcp:7000 connected").unwrap(); } else if !socket.is_active() && silent_socket_active { hprintln!("tcp:7000 disconnected").unwrap(); socket.close(); } // Update socket activeness silent_socket_active = socket.is_active(); if socket.can_recv() { // hprintln!("About to recv").unwrap(); hprintln!("{:?}", socket.recv(|buffer| { (buffer.len(), str::from_utf8(buffer).unwrap()) })).unwrap(); } } } } #[interrupt] fn ETH() { unsafe { ethernet::interrupt_handler() } } #[exception] fn SysTick() { TIME.fetch_add(1, Ordering::Relaxed); } #[exception] fn HardFault(ef: &cortex_m_rt::ExceptionFrame) -> ! { panic!("HardFault at {:#?}", ef); } #[exception] fn DefaultHandler(irqn: i16) { panic!("Unhandled exception (IRQn = {})", irqn); }