#![no_std] #![no_main] // use cortex_m::{asm, singleton}; pub mod serial; use core::str; use core::fmt::Write; // use nb::block; extern crate panic_itm; // use cortex_m::{iprintln, iprint}; use cortex_m_rt::entry; use embedded_hal::{ digital::v2::OutputPin, // blocking::delay::DelayMs }; // use stm32f1xx_hal::spi::SpiRegisterBlock; use stm32f1xx_hal::{ afio::AfioExt, rcc::RccExt, flash::FlashExt, gpio::GpioExt, time::U32Ext, // stm32::ITM, delay::Delay, spi::Spi, pac, // adc, prelude::* // time::Hertz }; use enc424j600::smoltcp_phy; use smoltcp::wire::{ EthernetAddress, IpAddress, IpCidr, Ipv6Cidr }; use smoltcp::iface::{ NeighborCache, EthernetInterfaceBuilder, // EthernetInterface }; use smoltcp::socket::{SocketSet, TcpSocket, TcpSocketBuffer}; /// Timer use core::cell::RefCell; use cortex_m::interrupt::Mutex; use cortex_m_rt::exception; use stm32f1xx_hal::{ rcc::Clocks, time::MilliSeconds, timer::{Timer, Event as TimerEvent}, stm32::SYST, serial::{ Config, Serial, // Tx }, // dma::*, // dma::dma1::*, // pac::* // dma::Half }; use smoltcp::time::Instant; /// Rate in Hz const TIMER_RATE: u32 = 20; /// Interval duration in milliseconds const TIMER_DELTA: u32 = 1000 / TIMER_RATE; /// Elapsed time in milliseconds static TIMER_MS: Mutex> = Mutex::new(RefCell::new(0)); /// Setup SysTick exception fn timer_setup(syst: SYST, clocks: Clocks) { let timer = Timer::syst(syst, &clocks); timer.start_count_down(TIMER_RATE.hz()).listen(TimerEvent::Update); } /// SysTick exception (Timer) #[exception] fn SysTick() { cortex_m::interrupt::free(|cs| { *TIMER_MS.borrow(cs) .borrow_mut() += TIMER_DELTA; }); } /// Obtain current time in milliseconds pub fn timer_now() -> MilliSeconds { let ms = cortex_m::interrupt::free(|cs| { *TIMER_MS.borrow(cs) .borrow() }); ms.ms() } ///spi use stm32f1xx_hal::{ stm32::SPI1, spi::Spi1Remap, gpio::{ gpiob::{PB3, PB4, PB5}, gpioc::PC13, Alternate, Output, PushPull, Input, Floating } }; type SpiEth = enc424j600::Enc424j600< Spi>, PB4>, PB5>)>, PC13> >; pub struct NetStorage { ip_addrs: [IpCidr; 1], neighbor_cache: [Option<(IpAddress, smoltcp::iface::Neighbor)>; 8], } static mut NET_STORE: NetStorage = NetStorage { // Placeholder for the real IP address, which is initialized at runtime. ip_addrs: [IpCidr::Ipv6( Ipv6Cidr::SOLICITED_NODE_PREFIX, )], neighbor_cache: [None; 8], }; #[entry()] fn main() -> ! { let mut cp = cortex_m::Peripherals::take().unwrap(); let dp = pac::Peripherals::take().unwrap(); cp.SCB.enable_icache(); cp.SCB.enable_dcache(&mut cp.CPUID); // Enable monotonic timer CYCCNT cp.DWT.enable_cycle_counter(); cp.DCB.enable_trace(); let mut flash = dp.FLASH.constrain(); let mut rcc = dp.RCC.constrain(); let dma1_chs = dp.DMA1.split(&mut rcc.ahb); let clocks = rcc .cfgr .use_hse(8.mhz()) .sysclk(72.mhz()) .hclk(72.mhz()) .pclk1(36.mhz()) .pclk2(72.mhz()) .adcclk(2.mhz()) .freeze(&mut flash.acr); let mut delay = Delay::new(cp.SYST, clocks); let mut gpioa = dp.GPIOA.split(&mut rcc.apb2); let mut gpiob = dp.GPIOB.split(&mut rcc.apb2); let mut gpioc = dp.GPIOC.split(&mut rcc.apb2); let mut afio = dp.AFIO.constrain(&mut rcc.apb2); // USART1 let tx = gpioa.pa9.into_alternate_push_pull(&mut gpioa.crh); let rx = gpioa.pa10; // Set up the usart device. Taks ownership over the USART register and tx/rx pins. The rest of // the registers are used to enable and configure the device. let serial = Serial::usart1( dp.USART1, (tx, rx), &mut afio.mapr, Config::default().baudrate(9600.bps()), clocks, &mut rcc.apb2, ); // let mut serial_tx = serial.split().0.with_dma(dma1_chs.4); let mut serial_tx = serial.split().0; // let dma_ch1 = dma1_chs.1; // // Setup ADC // let adc1 = adc::Adc::adc1(dp.ADC1, &mut rcc.apb2, clocks); // // Setup GPIOA // // Configure pa0 as an analog input // let adc_ch15 = gpioc.pc5.into_analog(&mut gpioc.crl); // let adc_dma = adc1.with_dma(adc_ch15, dma_ch1); // let buf = singleton!(: [u16; 8] = [0; 8]).unwrap(); // let (_buf, adc_dma) = adc_dma.read(buf).wait(); // let (_adc1, _adc_ch15, _dma_ch1) = adc_dma.split(); // // let buf = singleton!(: [[u16; 8]; 2] = [[0; 8]; 2]).unwrap(); // // let mut circ_buffer = adc_dma.circ_read(buf); // // while circ_buffer.readable_half().unwrap() != Half::First {} // // let _first_half = circ_buffer.peek(|half, _| *half).unwrap(); // // while circ_buffer.readable_half().unwrap() != Half::Second {} // // let _second_half = circ_buffer.peek(|half, _| *half).unwrap(); // // let (_buf, adc_dma) = circ_buffer.stop(); // // let (_adc1, _adc_ch15, _dma_ch1) = adc_dma.split(); // Init ITM // let mut itm = cp.ITM; // let stim0 = &mut itm.stim[0]; // iprintln!(stim0, // "Eth TCP Server on STM32-F103 via NIC100/ENC424J600"); // NIC100 / ENC424J600 Set-up let spi1 = dp.SPI1; let (_pa15, pb3, pb4) = afio.mapr.disable_jtag(gpioa.pa15, gpiob.pb3, gpiob.pb4); let spi1_sck = pb3.into_alternate_push_pull(&mut gpiob.crl); let spi1_miso = pb4;//.into_floating_input(&mut gpiob.crl); let spi1_mosi = gpiob.pb5.into_alternate_push_pull(&mut gpiob.crl); let spi1_nss = gpioc.pc13.into_push_pull_output(&mut gpioc.crh); // Create SPI1 for HAL let eth_iface = { let mut spi_eth = { let spi_eth_port = Spi::spi1( spi1, (spi1_sck, spi1_miso, spi1_mosi), &mut afio.mapr, enc424j600::spi::interfaces::SPI_MODE, // Hertz(enc424j600::spi::interfaces::SPI_CLOCK_FREQ), 9.mhz(), clocks, &mut rcc.apb2,); SpiEth::new(spi_eth_port, spi1_nss) .cpu_freq_mhz(72) }; // Init controller match spi_eth.reset(&mut delay) { Ok(_) => { // iprintln!(stim0, "Initializing Ethernet...") serial_tx.write_fmt(format_args!("Initializing Ethernet...\n")).unwrap(); } Err(_) => { panic!("Ethernet initialization failed!") } } // Read MAC let mut eth_mac_addr: [u8; 6] = [0; 6]; spi_eth.read_mac_addr(&mut eth_mac_addr).unwrap(); for i in 0..6 { let byte = eth_mac_addr[i]; match i { // 0 => iprint!(stim0, "MAC Address = {:02x}-", byte), // 1..=4 => iprint!(stim0, "{:02x}-", byte), // 5 => iprint!(stim0, "{:02x}\n", byte), 0 => { serial_tx.write_fmt(format_args!("MAC Address = {:02x}-", byte)).unwrap(); }, 1..=4 => { serial_tx.write_fmt(format_args!("{:02x}-", byte)).unwrap(); }, 5 => { serial_tx.write_fmt(format_args!("{:02x}\n", byte)).unwrap(); }, _ => () }; } // Init Rx/Tx buffers spi_eth.init_rxbuf().unwrap(); spi_eth.init_txbuf().unwrap(); // iprintln!(stim0, "Ethernet controller initialized"); serial_tx.write_fmt(format_args!("Ethernet controller initialized\n")).unwrap(); // Init smoltcp interface let eth_iface = { let device = smoltcp_phy::SmoltcpDevice::new(spi_eth); let store = unsafe { &mut NET_STORE }; store.ip_addrs[0] = IpCidr::new(IpAddress::v4(192, 168, 1, 88), 24); let neighbor_cache = NeighborCache::new(&mut store.neighbor_cache[..]); EthernetInterfaceBuilder::new(device) .ethernet_addr(EthernetAddress(eth_mac_addr)) .neighbor_cache(neighbor_cache) .ip_addrs(&mut store.ip_addrs[..]) .finalize() }; // iprintln!(stim0, "Ethernet interface initialized"); serial_tx.write_fmt(format_args!("Ethernet interface initialized\n")).unwrap(); eth_iface }; // Setup SysTick after releasing SYST from Delay // Reference to stm32-eth:examples/ip.rs timer_setup(delay.free(), clocks); // iprintln!(stim0, "Timer initialized"); let mut led = gpioc.pc0.into_push_pull_output(&mut gpioc.crl); led.set_high().unwrap(); loop { // let stim0 = &mut c.resources.itm.stim[0]; let mut iface = eth_iface; // Copied / modified from smoltcp: // examples/loopback.rs let echo_socket = { static mut TCP_SERVER_RX_DATA: [u8; 1024] = [0; 1024]; static mut TCP_SERVER_TX_DATA: [u8; 1024] = [0; 1024]; let tcp_rx_buffer = TcpSocketBuffer::new(unsafe { &mut TCP_SERVER_RX_DATA[..] }); let tcp_tx_buffer = TcpSocketBuffer::new(unsafe { &mut TCP_SERVER_TX_DATA[..] }); TcpSocket::new(tcp_rx_buffer, tcp_tx_buffer) }; let greet_socket = { static mut TCP_SERVER_RX_DATA: [u8; 256] = [0; 256]; static mut TCP_SERVER_TX_DATA: [u8; 256] = [0; 256]; let tcp_rx_buffer = TcpSocketBuffer::new(unsafe { &mut TCP_SERVER_RX_DATA[..] }); let tcp_tx_buffer = TcpSocketBuffer::new(unsafe { &mut TCP_SERVER_TX_DATA[..] }); TcpSocket::new(tcp_rx_buffer, tcp_tx_buffer) }; let mut socket_set_entries = [None, None]; let mut socket_set = SocketSet::new(&mut socket_set_entries[..]); let greet_handle = socket_set.add(greet_socket); { let store = unsafe { &mut NET_STORE }; // iprintln!(stim0, // "TCP sockets will listen at {}", store.ip_addrs[0].address()); serial_tx.write_fmt(format_args!("TCP sockets will listen at {}\n", store.ip_addrs[0].address())).unwrap(); } // Copied / modified from: // smoltcp:examples/loopback.rs, examples/server.rs; // stm32-eth:examples/ip.rs, // git.m-labs.hk/M-Labs/tnetplug loop { // Poll let now = timer_now().0; let instant = Instant::from_millis(now as i64); match iface.poll(&mut socket_set, instant) { Ok(_) => { }, Err(e) => { // iprintln!(stim0, "[{}] Poll error: {:?}", instant, e) serial_tx.write_fmt(format_args!("[{}] Poll error: {:?}\n", instant, e)).unwrap(); } } // Control the "greeting" socket (:4321) { let mut socket = socket_set.get::(greet_handle); if !socket.is_open() { // iprintln!(stim0, // "[{}] Listening to port 4321 for greeting, \ // please connect to the port", instant); serial_tx.write_fmt(format_args!("[{}] Listening to port 4321 for greeting, please connect to the port\n", instant)).unwrap(); socket.listen(4321).unwrap(); // socket.set_timeout(Some(smoltcp::time::Duration::from_millis(10000))); } if socket.can_send() { let greeting = "Welcome to the server demo for STM32F103!"; write!(socket, "{}\n", greeting).unwrap(); // iprintln!(stim0, // "[{}] Greeting sent, socket closed", instant); serial_tx.write_fmt(format_args!("[{}] Greeting sent, socket closed\n", instant)).unwrap(); socket.close(); } if socket.can_recv() { // iprintln!(stim0, // "[{}] Received packet: {:?}", instant, socket.recv(|buffer| { // (buffer.len(), str::from_utf8(buffer).unwrap()) // })); serial_tx.write_fmt(format_args!("[{}] Received packet: {:?}\n", instant, socket.recv(|buffer| {(buffer.len(), str::from_utf8(buffer).unwrap())}))).unwrap(); } } } } }