Still an issue where connecting to a socket the first time will time out, unsure what the cause of that or where to start, but can ignore for now and figure out more when I have more info later
250 lines
7.1 KiB
Rust
250 lines
7.1 KiB
Rust
#![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::<TcpSocket>(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::<TcpSocket>(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::<TcpSocket>(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::<u32>(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<T>(addr: u32, value: T) {
|
|
write_volatile(addr as *mut T, value);
|
|
}
|
|
|
|
unsafe fn read_reg<T>(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
|
|
}
|
|
})
|
|
}
|