#![no_std] #![no_main] #[macro_use] extern crate log; #[macro_use] extern crate lazy_static; use smoltcp as net; use stm32h7xx_hal::ethernet; use stm32h7xx_hal::{gpio::Speed, prelude::*, spi, pac}; use embedded_hal::{ blocking::spi::Transfer, digital::v2::OutputPin, }; use core::sync::atomic::{AtomicU32, Ordering}; use core::fmt::Write; use core::str; // use heapless::{consts, String}; use cortex_m; use cortex_m::iprintln; use cortex_m_rt::{ entry, exception, }; // use cortex_m_semihosting::hprintln; // use panic_halt as _; use panic_itm as _; use rtic::cyccnt::{Instant, U32Ext}; use log::info; use log::debug; use log::trace; use log::warn; use nb::block; use minimq::{ embedded_nal::{IpAddr, Ipv4Addr, TcpStack, SocketAddr, Mode}, MqttClient, QoS, }; use firmware::nal_tcp_client::{NetworkStack, NetStorage, NetworkInterface}; use firmware::{Urukul}; use firmware::cpld::{CPLD}; #[link_section = ".sram3.eth"] static mut DES_RING: ethernet::DesRing = ethernet::DesRing::new(); // Logging setup #[path = "util/logger.rs"] mod logger; #[path = "util/clock.rs"] mod clock; // End of logging setup // static TIME: AtomicU32 = AtomicU32::new(0); #[entry] fn main() -> ! { // logger::semihosting_init(); let clock = clock::Clock::new(); let mut cp = cortex_m::Peripherals::take().unwrap(); let dp = pac::Peripherals::take().unwrap(); cp.DWT.enable_cycle_counter(); // Enable SRAM3 for the descriptor ring. dp.RCC.ahb2enr.modify(|_, w| w.sram3en().set_bit()); // Reset RCC clock dp.RCC.rsr.write(|w| w.rmvf().set_bit()); let pwr = dp.PWR.constrain(); let vos = pwr.freeze(); let rcc = dp.RCC.constrain(); let ccdr = rcc .use_hse(8.mhz()) .sysclk(400.mhz()) .hclk(200.mhz()) // .per_ck(100.mhz()) .pll1_q_ck(48.mhz()) // for SPI .pll1_r_ck(400.mhz()) // for TRACECK // .pll2_p_ck(100.mhz()) // .pll2_q_ck(100.mhz()) .freeze(vos, &dp.SYSCFG); unsafe { logger::enable_itm(&dp.DBGMCU, &mut cp.DCB, &mut cp.ITM); } let mut delay = cp.SYST.delay(ccdr.clocks); 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 gpiod = dp.GPIOD.split(ccdr.peripheral.GPIOD); let gpioe = dp.GPIOE.split(ccdr.peripheral.GPIOE); let gpiof = dp.GPIOF.split(ccdr.peripheral.GPIOF); let gpiog = dp.GPIOG.split(ccdr.peripheral.GPIOG); let mut yellow_led = gpioe.pe1.into_push_pull_output(); yellow_led.set_low().unwrap(); let mut red_led = gpiob.pb14.into_push_pull_output(); red_led.set_high().unwrap(); let mut green_led = gpiob.pb0.into_push_pull_output(); green_led.set_low().unwrap(); // gpiob.pb3.into_alternate_af0().set_speed(Speed::VeryHigh); logger::init(); // Configure ethernet IO { let _rmii_refclk = gpioa.pa1.into_alternate_af11().set_speed(Speed::VeryHigh); let _rmii_mdio = gpioa.pa2.into_alternate_af11().set_speed(Speed::VeryHigh); let _rmii_mdc = gpioc.pc1.into_alternate_af11().set_speed(Speed::VeryHigh); let _rmii_crs_dv = gpioa.pa7.into_alternate_af11().set_speed(Speed::VeryHigh); let _rmii_rxd0 = gpioc.pc4.into_alternate_af11().set_speed(Speed::VeryHigh); let _rmii_rxd1 = gpioc.pc5.into_alternate_af11().set_speed(Speed::VeryHigh); let _rmii_tx_en = gpiog.pg11.into_alternate_af11().set_speed(Speed::VeryHigh); let _rmii_txd0 = gpiog.pg13.into_alternate_af11().set_speed(Speed::VeryHigh); let _rmii_txd1 = gpiob.pb13.into_alternate_af11().set_speed(Speed::VeryHigh); } // Configure ethernet let mac_addr = net::wire::EthernetAddress([0xAC, 0x6F, 0x7A, 0xDE, 0xD6, 0xC8]); let (eth_dma, mut eth_mac) = unsafe { ethernet::new_unchecked( dp.ETHERNET_MAC, dp.ETHERNET_MTL, dp.ETHERNET_DMA, &mut DES_RING, mac_addr.clone(), ) }; unsafe { ethernet::enable_interrupt() } let mut ip_addrs = [net::wire::IpCidr::new(net::wire::IpAddress::v4(192, 168, 1, 200), 24)]; let mut neighbor_cache_entries = [None; 8]; let mut neighbor_cache = net::iface::NeighborCache::new(&mut neighbor_cache_entries[..]); neighbor_cache.fill( net::wire::IpAddress::v4(192, 168, 1, 125), net::wire::EthernetAddress([0x2C, 0xF0, 0x5D, 0x26, 0xB8, 0x2F]), clock.elapsed(), ); let mut net_interface = net::iface::EthernetInterfaceBuilder::new(eth_dma) .ethernet_addr(mac_addr) .neighbor_cache(neighbor_cache) .ip_addrs(&mut ip_addrs[..]) .finalize(); /* * Using SPI1, AF5 * SCLK -> PA5 * MOSI -> PB5 * MISO -> PA6 * CS -> 0: PB12, 1: PA15, 2: PC7 * I/O_Update -> PB15 */ let sclk = gpioa.pa5.into_alternate_af5(); let mosi = gpiob.pb5.into_alternate_af5(); let miso = gpioa.pa6.into_alternate_af5(); let (cs0, cs1, cs2) = ( gpiob.pb12.into_push_pull_output(), gpioa.pa15.into_push_pull_output(), gpioc.pc7.into_push_pull_output(), ); let io_update = gpiob.pb15.into_push_pull_output(); let spi = dp.SPI1.spi( (sclk, miso, mosi), spi::MODE_0, 3.mhz(), ccdr.peripheral.SPI1, &ccdr.clocks, ); let cpld = CPLD::new(spi, (cs0, cs1, cs2), io_update); let parts = cpld.split(); let urukul = Urukul::new( parts.spi1, parts.spi2, parts.spi3, parts.spi4, parts.spi5, parts.spi6, parts.spi7, [25_000_000, 25_000_000, 25_000_000, 25_000_000] ); cp.SCB.invalidate_icache(); cp.SCB.enable_icache(); // let mut time: u32 = 0; // let mut next_ms = Instant::now(); // next_ms += 400_000.cycles(); let mut socket_set_entries: [_; 8] = Default::default(); let mut sockets = net::socket::SocketSet::new(&mut socket_set_entries[..]); let mut rx_storage = [0; 4096]; let mut tx_storage = [0; 4096]; let tcp_socket = { let tx_buffer = net::socket::TcpSocketBuffer::new(&mut tx_storage[..]); let rx_buffer = net::socket::TcpSocketBuffer::new(&mut rx_storage[..]); net::socket::TcpSocket::new(tx_buffer, rx_buffer) }; let handle = sockets.add(tcp_socket); // delay.delay_ms(2000_u16); green_led.set_high().unwrap(); { let mut socket = sockets.get::(handle); socket.connect((net::wire::IpAddress::v4(192, 168, 1, 125), 1883), 49500).unwrap(); socket.set_timeout(Some(net::time::Duration::from_millis(2000))); debug!("connect!"); } yellow_led.set_low().unwrap(); red_led.set_high().unwrap(); let mut green = true; let mut connected = false; debug!("Poll link status: {}", eth_mac.phy_poll_link()); while !eth_mac.phy_poll_link() {} debug!("Poll link status: {}", eth_mac.phy_poll_link()); loop { // let timestamp = net::time::Instant::from_millis(TIME.load(Ordering::Relaxed) as i64); while !eth_mac.phy_poll_link() {} match net_interface.poll(&mut sockets, clock.elapsed()) { Ok(_) => {}, Err(e) => { debug!("poll error: {}", e); } } { let mut socket = sockets.get::(handle); info!("Socket state: {} at time {}", socket.state(), clock.elapsed()); if socket.may_recv() { yellow_led.set_high().unwrap(); red_led.set_low().unwrap(); let data = socket.recv(|data| { (data.len(), data) }).unwrap(); if socket.can_send() { socket.send_slice("response".as_bytes()).unwrap(); } } if socket.may_send() { yellow_led.set_high().unwrap(); red_led.set_low().unwrap(); debug!("close"); socket.close(); } } match net_interface.poll_delay(&sockets, clock.elapsed()) { Some(net::time::Duration {millis :0}) => { clock.advance(net::time::Duration::from_millis(1)); continue; } Some(time_delay) => { green_led.set_low().unwrap(); delay.delay_ms(time_delay.total_millis() as u32); green_led.set_high().unwrap(); clock.advance(time_delay) }, None => { // delay.delay_ms(1_u32); clock.advance(net::time::Duration::from_millis(1)) }, } } }