From ae5a2444f7ed74ad6eddfbcff40c7fdaadcd42b4 Mon Sep 17 00:00:00 2001 From: Zheng-Jiakun Date: Tue, 31 Aug 2021 17:42:14 +0800 Subject: [PATCH] try to move ethernet pdriver to a single file (not working at the moment) --- src/ethernet.rs | 202 ++++++++++++++++++++++++++++++++ src/main.rs | 301 ++++++++++++------------------------------------ 2 files changed, 276 insertions(+), 227 deletions(-) create mode 100644 src/ethernet.rs diff --git a/src/ethernet.rs b/src/ethernet.rs new file mode 100644 index 0000000..59dc4e7 --- /dev/null +++ b/src/ethernet.rs @@ -0,0 +1,202 @@ +use enc424j600::smoltcp_phy; + +use smoltcp::wire::{ + EthernetAddress, IpAddress, IpCidr, Ipv6Cidr +}; +use smoltcp::iface::{NeighborCache, EthernetInterfaceBuilder, EthernetInterface}; +use smoltcp::socket::{SocketSet, TcpSocket, TcpSocketBuffer}; +use core::str; +use core::fmt::Write; + +use smoltcp::time::Instant; + +use cortex_m_rt::exception; + +///spi +use stm32f1xx_hal::{ + time::U32Ext, + delay::Delay +}; + +/// Timer +use core::cell::RefCell; +use cortex_m::interrupt::Mutex; +use stm32f1xx_hal::{ + time::MilliSeconds, + timer::{Timer, Event as TimerEvent}, + rcc::Clocks, + stm32::SYST +}; + +/// 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() +} + +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], +}; + +pub fn ethernet_init ( + spi_eth: SpiEth, + delay: Delay, + clocks: &Clocks +) + // -> EthernetInterface> +{ + // Init controller + match spi_eth.reset(&mut delay) { + Ok(_) => { + // 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); + for i in 0..6 { + let byte = eth_mac_addr[i]; + match i { + // 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(); + spi_eth.init_txbuf(); + // 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() + }; + // serial_tx.write_fmt(format_args!("Ethernet interface initialized\n")).unwrap(); + + // Setup SysTick after releasing SYST from Delay + // Reference to stm32-eth:examples/ip.rs + timer_setup(delay.free(), *clocks); + // serial_tx.write_fmt(format_args!("Timer initialized\n")).unwrap(); + + // eth_iface + let iface = eth_iface; + + 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 }; + // 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) => { + // 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() { + // 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(); + // serial_tx.write_fmt(format_args!("[{}] Greeting sent, socket closed\n", instant)).unwrap(); + socket.close(); + } + + if socket.can_recv() { + // serial_tx.write_fmt(format_args!("[{}] Received packet: {:?}\n", + // instant, socket.recv(|buffer| {(buffer.len(), str::from_utf8(buffer).unwrap())}))).unwrap(); + } + } + } +} + + + +// pub fn ethernet_test +// (mut iface: EthernetInterface>) +// { +// // Copied / modified from smoltcp: +// // examples/loopback.rs + +// } \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index a8225cc..95d457e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,14 +1,19 @@ #![no_std] #![no_main] -// use cortex_m::{asm, singleton}; +use cortex_m::{singleton}; + +pub mod ethernet; +use ethernet::{ + ethernet_init, + // ethernet_test +}; pub mod serial; -use core::str; -use core::fmt::Write; +// 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::{ @@ -22,35 +27,20 @@ use stm32f1xx_hal::{ flash::FlashExt, gpio::GpioExt, time::U32Ext, - // stm32::ITM, delay::Delay, spi::Spi, pac, - // adc, + 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 cortex_m_rt::exception; use stm32f1xx_hal::{ - rcc::Clocks, - time::MilliSeconds, - timer::{Timer, Event as TimerEvent}, - stm32::SYST, + timer::{Timer}, serial::{ Config, Serial, @@ -61,38 +51,11 @@ use stm32f1xx_hal::{ // 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() -} +use stm32f1xx_hal::{ + gpio::{gpioc}, + pac::{interrupt, Interrupt, TIM3}, + timer::{CountDownTimer, Event}, +}; ///spi use stm32f1xx_hal::{ @@ -109,18 +72,36 @@ type SpiEth = enc424j600::Enc424j600< 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], -}; +// A type definition for the GPIO pin to be used for our LED +type LEDPIN = gpioc::PC0>; +// Make LED pin globally available +static G_LED: Mutex>> = Mutex::new(RefCell::new(None)); +// Make timer interrupt registers globally available +static G_TIM: Mutex>>> = Mutex::new(RefCell::new(None)); +// Define an interupt handler, i.e. function to call when interrupt occurs. +// This specific interrupt will "trip" when the timer TIM2 times out +#[interrupt] +fn TIM3() { + static mut LED: Option = None; + static mut TIM: Option> = None; + + let led = LED.get_or_insert_with(|| { + cortex_m::interrupt::free(|cs| { + // Move LED pin here, leaving a None in its place + G_LED.borrow(cs).replace(None).unwrap() + }) + }); + + let tim = TIM.get_or_insert_with(|| { + cortex_m::interrupt::free(|cs| { + G_TIM.borrow(cs).replace(None).unwrap() + }) + }); + + let _ = led.toggle(); + let _ = tim.wait(); +} #[entry()] fn main() -> ! { @@ -137,7 +118,7 @@ fn main() -> ! { let mut flash = dp.FLASH.constrain(); let mut rcc = dp.RCC.constrain(); - let dma1_chs = dp.DMA1.split(&mut rcc.ahb); + // let dma1_chs = dp.DMA1.split(&mut rcc.ahb); let clocks = rcc .cfgr @@ -172,9 +153,10 @@ fn main() -> ! { ); // let mut serial_tx = serial.split().0.with_dma(dma1_chs.4); - let mut serial_tx = serial.split().0; + let (mut serial_tx, mut _serial_rx) = serial.split(); - + + // //ADC1 // let dma_ch1 = dma1_chs.1; // // Setup ADC // let adc1 = adc::Adc::adc1(dp.ADC1, &mut rcc.apb2, clocks); @@ -195,13 +177,6 @@ fn main() -> ! { // // 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; @@ -212,165 +187,37 @@ fn main() -> ! { 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,); + 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) - }; + let spi_eth = 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!") - } - } + ethernet_init(spi_eth, delay, &clocks); - // 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(); + // Move the pin into our global storage + cortex_m::interrupt::free(|cs| *G_LED.borrow(cs).borrow_mut() = Some(led)); + // Set up a timer expiring after 1s + let mut timer = Timer::tim3(dp.TIM3, &clocks, &mut rcc.apb1).start_count_down(1.hz()); + // Generate an interrupt when the timer expires + timer.listen(Event::Update); + // Move the timer into our global storage + cortex_m::interrupt::free(|cs| *G_TIM.borrow(cs).borrow_mut() = Some(timer)); + unsafe { + cortex_m::peripheral::NVIC::unmask(Interrupt::TIM3); + } + 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(); - } - } - } + // ethernet_test(); } } \ No newline at end of file