#![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::{self, Socket}; use smoltcp::time::Duration; use smoltcp::wire::{IpAddress, Ipv4Address}; use smoltcp::{ iface::{SocketSet, SocketStorage}, socket::tcp::Socket as TcpSocket, socket::tcp::SocketBuffer, time::Instant, wire::HardwareAddress, }; mod command_interface; mod eth; mod i2c; mod logging; mod mcp4726; mod proto; mod uart; 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); // TODO these values are obscene, should fix the underlying bug sock.set_keep_alive(Some(Duration::from_secs(2))); sock.set_timeout(Some(Duration::from_secs(10))) } let mut last_blink: u32 = 0; let mut toggle = false; //defmt::info!("Done setup"); // Set up timer for polling events unsafe { // 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 } 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)); } } 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"); } } } 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 } }) }