#![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::wire::{IpAddress, Ipv4Address}; use smoltcp::{ iface::{SocketSet, SocketStorage}, time::Instant, wire::HardwareAddress, }; mod eth; mod i2c; mod mcp4726; mod uart; mod litex_uart; mod logging; const MAC: [u8; 6] = [0xA0, 0xBB, 0xCC, 0xDD, 0xEE, 0xF0]; static mut SECONDS: u32 = 0; /// External interrupt handler #[export_name = "MachineExternal"] fn external_interrupt_handler() { let cause = riscv::register::mcause::read(); let mut uart = litex_uart::LiteXUart::new(0xf000_4000); writeln!(uart, "mcause: {}", cause.bits()); if (cause.is_interrupt()) { let mut uart = litex_uart::LiteXUart::new(0xf000_4000); writeln!(uart, "mcause: {}", cause.code()); if cause.code() == 1 { // TIMER0 event, we have reset so count another second } } } // 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; let mut uart = litex_uart::LiteXUart::new(0xf000_4000); writeln!(uart, "uart init"); // enable timer let mut device = unsafe { eth::LiteEthDevice::try_init(0xf000_0800, 0x8000_0000).unwrap() }; writeln!(uart, "eth init"); 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 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); } loop { let now = millis(); if now - last_blink > 1000 { last_blink = now; toggle = !toggle; write_led(if toggle { 1 } else { 0 }); let val: u32 = unsafe {read_reg(0x8000_2000)}; writeln!(uart, "Sampler value: 0x{:08x}", val).unwrap(); } if iface.poll(Instant::from_millis(now), &mut device, &mut socket_set) { } handle_timer_event(); } } fn handle_timer_event() { unsafe { if read_reg::(0xf000_3818) == 0 { 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 } }) }