#![no_std] #![no_main] // TODO remove #![allow(unused)] extern crate panic_halt; use core::fmt::Write; use core::{ arch::asm, ptr::{read_volatile, write_volatile}, }; use embedded_hal::prelude::{_embedded_hal_blocking_i2c_Read, _embedded_hal_blocking_i2c_Write}; use mcp4726::Status; use riscv_rt::entry; use smoltcp::socket::{Socket, self}; use smoltcp::time::Duration; use smoltcp::wire::{IpAddress, Ipv4Address}; use smoltcp::{ iface::{SocketSet, SocketStorage}, time::Instant, wire::HardwareAddress, socket::tcp::Socket as TcpSocket, socket::tcp::SocketBuffer, }; mod eth; mod i2c; mod mcp4726; mod uart; mod logging; mod proto; mod command_interface; const MAC: [u8; 6] = [0xA0, 0xBB, 0xCC, 0xDD, 0xEE, 0xF0]; static mut SECONDS: u32 = 0; // use `main` as the entry point of this application // `main` is not allowed to return #[entry] fn main() -> ! { //unsafe { eth::init(); } //let blink_period = unsafe { // if eth::is_wishbone_correct() { // 10_000_000 // } else { // 500_000 // } //}; let blink_period = 10_000_000u32; // enable timer let mut device = unsafe { eth::LiteEthDevice::try_init(0xf000_0800, 0x8000_0000).unwrap() }; use smoltcp::wire::{EthernetAddress, HardwareAddress}; let mut config = smoltcp::iface::Config::default(); config.hardware_addr = Some(HardwareAddress::Ethernet(EthernetAddress::from_bytes(&MAC))); let mut iface = smoltcp::iface::Interface::new(config, &mut device); // Set address iface.update_ip_addrs(|ip_addrs| { ip_addrs .push(smoltcp::wire::IpCidr::new( IpAddress::Ipv4(Ipv4Address::new(192, 168, 88, 69)), 24, )) .unwrap(); }); iface .routes_mut() .add_default_ipv4_route(Ipv4Address::new(192, 168, 88, 1)) .unwrap(); // Create socket set with 4 available let mut socket_storage = [SocketStorage::EMPTY; 4]; let mut socket_set = SocketSet::new(&mut socket_storage[..]); let mut tx_storage = [0u8; 64]; let mut rx_storage = [0u8; 64]; let mut tx_buf = SocketBuffer::new(&mut tx_storage[..]); let mut rx_buf = SocketBuffer::new(&mut rx_storage[..]); let mut command_socket = socket_set.add(TcpSocket::new(tx_buf, rx_buf)); // Set a keepalive on the socket to handle unexpected client disconnects { let mut sock = socket_set.get_mut::(command_socket); sock.set_keep_alive(Some(Duration::from_secs(5))); sock.set_timeout(Some(Duration::from_secs(5))) } let mut logger_tx_storage = [0u8; 128]; let mut logger_rx_storage = [0u8; 16]; let mut logger_tx_buf = SocketBuffer::new(&mut logger_tx_storage[..]); let mut logger_rx_buf = SocketBuffer::new(&mut logger_rx_storage[..]); let mut logger_socket = socket_set.add(TcpSocket::new(logger_tx_buf, logger_rx_buf)); unsafe { logging::set_logger_socket(Some(socket_set.get_mut::(logger_socket))); } let mut last_blink: u32 = 0; let mut toggle = false; //defmt::info!("Done setup"); unsafe { //riscv::interrupt::enable(); //riscv::register::mie::set_mext(); //riscv::register::mie::set_msoft(); // Enable UART rx event for test //write_reg(0xf000_4014, 1u32); // Timer stuff write_reg(0xf000_3808, 0u32); // Disable timer write_reg(0xf000_3800, 0u32); // Set LOAD value write_reg(0xf000_3804, 60_000_000u32); // Set RELOAD value write_reg(0xf000_3808, 1u32); // Enable timer // Enable timer event //write_reg(0xf000_381c, 1u32); } let mut cmd = command_interface::CommandInterface::new(); loop { let now = millis(); // TODO the need for the second check screams something is unsound somewhere if now - last_blink > 1000 && now > last_blink { last_blink = now; toggle = !toggle; write_led(if toggle { 1 } else { 0 }); let val: u32 = unsafe {read_reg(0x8000_2000)}; } // TODO I think the timer might actually stop until the event is cleared? this may pose // problems, might explain why moving this above the smoltcp stuff "broke" things handle_timer_event(); iface.poll(Instant::from_millis(now), &mut device, &mut socket_set); // TODO first connection to a socket takes a while to establish, and can time out, why? cmd.run(socket_set.get_mut(command_socket)); //if iface.poll(Instant::from_millis(now), &mut device, &mut socket_set) { //let sock = socket_set.get_mut::(command_socket); //if !sock.is_open() { // sock.listen(2000); //} //let mut echo_tx_buf = [0u8; 32]; //match sock.recv(|buf| { // if buf.len() > 0 { // // Copy into send buffer // let rd_len = core::cmp::min(buf.len(), echo_tx_buf.len()); // &echo_tx_buf[..rd_len].copy_from_slice(&buf[..rd_len]); // defmt::trace!("RX data command"); // // Return slice to send // (rd_len, Some(&echo_tx_buf[..rd_len])) // } else { // (0, None) // } //}) { // Err(_) => { // // Close the socket, re-open it later // //sock.abort(); // // Is doing this immediately legal? // //sock.listen(2000); // } // // Some data to send // Ok(Some(tx_data)) => { // match sock.send_slice(tx_data) { // Err(_) => { // //sock.abort(); // //sock.listen(2000); // } // _ => (), // } // } // // No data to send // Ok(None) => (), //} //} } } fn handle_timer_event() { unsafe { if read_reg::(0xf000_3818) == 0 { // No event yet, continue return; } // Clear TIMER0 event status, and update time write_reg(0xf000_3818, 1u32); SECONDS += 1; } } fn busy_wait(ms: u32) { //let start = millis(); //while millis() - start < ms { // unsafe { // asm!("nop"); // } //} for i in 0..ms*20_000 { unsafe {asm!("nop");} } } fn write_led(val: u32) { unsafe { write_reg(0xf000_2000, val); } } unsafe fn write_reg(addr: u32, value: T) { write_volatile(addr as *mut T, value); } unsafe fn read_reg(addr: u32) -> T { return read_volatile(addr as *mut T); } fn millis() -> u32 { riscv::interrupt::free(|| { unsafe { // Latch timer value write_reg(0xf000_380c, 1u32); // Read timer value let val: u32 = read_reg(0xf000_3810); let val = 60_000_000 - val; (SECONDS * 1000) + val / 60_000 } }) }