#![feature(used, const_fn, core_float, asm)] #![no_std] extern crate cortex_m; extern crate cortex_m_rt; extern crate tm4c129x; extern crate smoltcp; use core::cell::{Cell, RefCell}; use core::fmt; use cortex_m::exception::Handlers as ExceptionHandlers; use cortex_m::interrupt::Mutex; use tm4c129x::interrupt::Interrupt; use tm4c129x::interrupt::Handlers as InterruptHandlers; use smoltcp::Error; use smoltcp::wire::{EthernetAddress, IpAddress}; use smoltcp::iface::{ArpCache, SliceArpCache, EthernetInterface}; use smoltcp::socket::{AsSocket, SocketSet}; use smoltcp::socket::{TcpSocket, TcpSocketBuffer}; #[macro_export] macro_rules! print { ($($arg:tt)*) => ({ use core::fmt::Write; write!($crate::UART0, $($arg)*).unwrap() }) } #[macro_export] macro_rules! println { ($fmt:expr) => (print!(concat!($fmt, "\n"))); ($fmt:expr, $($arg:tt)*) => (print!(concat!($fmt, "\n"), $($arg)*)); } #[macro_use] mod board; mod ethmac; mod pid; mod loop_anode; mod loop_cathode; mod electrometer; mod http; mod pages; static TIME: Mutex> = Mutex::new(Cell::new(0)); fn get_time() -> u64 { cortex_m::interrupt::free(|cs| { TIME.borrow(cs).get() }) } static LOOP_ANODE: Mutex> = Mutex::new(RefCell::new( loop_anode::Controller::new())); static LOOP_CATHODE: Mutex> = Mutex::new(RefCell::new( loop_cathode::Controller::new())); static ELECTROMETER: Mutex> = Mutex::new(RefCell::new( electrometer::Electrometer::new())); pub struct UART0; impl fmt::Write for UART0 { fn write_str(&mut self, s: &str) -> Result<(), fmt::Error> { for c in s.bytes() { unsafe { let uart_0 = tm4c129x::UART0.get(); while (*uart_0).fr.read().txff().bit() {} (*uart_0).dr.write(|w| w.data().bits(c)) } } Ok(()) } } const TCP_RX_BUFFER_SIZE: usize = 256; const TCP_TX_BUFFER_SIZE: usize = 8192; macro_rules! create_socket_storage { ($rx_storage:ident, $tx_storage:ident) => ( let mut $rx_storage = [0; TCP_RX_BUFFER_SIZE]; let mut $tx_storage = [0; TCP_TX_BUFFER_SIZE]; ) } macro_rules! create_socket { ($set:ident, $rx_storage:ident, $tx_storage:ident, $target:ident) => ( let tcp_rx_buffer = TcpSocketBuffer::new(&mut $rx_storage[..]); let tcp_tx_buffer = TcpSocketBuffer::new(&mut $tx_storage[..]); let tcp_socket = TcpSocket::new(tcp_rx_buffer, tcp_tx_buffer); let $target = $set.add(tcp_socket); ) } fn main() { // Enable the FPU unsafe { asm!(" PUSH {R0, R1} LDR.W R0, =0xE000ED88 LDR R1, [R0] ORR R1, R1, #(0xF << 20) STR R1, [R0] DSB ISB POP {R0, R1} "); } // Beware of the compiler inserting FPU instructions // in the prologue of functions before the FPU is enabled! main_with_fpu(); } #[inline(never)] fn main_with_fpu() { board::init(); cortex_m::interrupt::free(|cs| { let nvic = tm4c129x::NVIC.borrow(cs); nvic.enable(Interrupt::ADC0SS0); let mut loop_anode = LOOP_ANODE.borrow(cs).borrow_mut(); let mut loop_cathode = LOOP_CATHODE.borrow(cs).borrow_mut(); // ZJ-10 let anode = 165.0; let cathode_bias = 50.0; let emission = 0.5e-3; // ZJ-27 /*let anode = 225.0; let cathode_bias = 25.0; let emission = 1.0e-3;*/ // ZJ-12 /*let anode = 200.0; let cathode_bias = 50.0; let emission = 4.0e-3;*/ // G8130 /*let anode = 180.0; let cathode_bias = 30.0; let emission = 4.0e-3;*/ loop_anode.set_target(anode); loop_cathode.set_emission_target(emission); loop_cathode.set_bias_target(cathode_bias); }); println!(r#" _ _ (_) | | _ ___ _ __ _ __ __ _| | | |/ _ \| '_ \| '_ \ / _` | |/ / | | (_) | | | | |_) | (_| | < |_|\___/|_| |_| .__/ \__,_|_|\_\ | | |_| "#); let hardware_addr = EthernetAddress(board::get_mac_address()); let mut protocol_addrs = [IpAddress::v4(192, 168, 69, 1)]; println!("MAC {} IP {}", hardware_addr, protocol_addrs[0]); let mut arp_cache_entries: [_; 8] = Default::default(); let mut arp_cache = SliceArpCache::new(&mut arp_cache_entries[..]); ethmac::init(hardware_addr.0); let mut device = ethmac::EthernetDevice; let mut iface = EthernetInterface::new( &mut device, &mut arp_cache as &mut ArpCache, hardware_addr, &mut protocol_addrs[..]); create_socket_storage!(tcp_rx_storage0, tcp_tx_storage0); create_socket_storage!(tcp_rx_storage1, tcp_tx_storage1); create_socket_storage!(tcp_rx_storage2, tcp_tx_storage2); create_socket_storage!(tcp_rx_storage3, tcp_tx_storage3); create_socket_storage!(tcp_rx_storage4, tcp_tx_storage4); create_socket_storage!(tcp_rx_storage5, tcp_tx_storage5); create_socket_storage!(tcp_rx_storage6, tcp_tx_storage6); create_socket_storage!(tcp_rx_storage7, tcp_tx_storage7); let mut socket_set_entries: [_; 8] = Default::default(); let mut sockets = SocketSet::new(&mut socket_set_entries[..]); create_socket!(sockets, tcp_rx_storage0, tcp_tx_storage0, tcp_handle0); create_socket!(sockets, tcp_rx_storage1, tcp_tx_storage1, tcp_handle1); create_socket!(sockets, tcp_rx_storage2, tcp_tx_storage2, tcp_handle2); create_socket!(sockets, tcp_rx_storage3, tcp_tx_storage3, tcp_handle3); create_socket!(sockets, tcp_rx_storage4, tcp_tx_storage4, tcp_handle4); create_socket!(sockets, tcp_rx_storage5, tcp_tx_storage5, tcp_handle5); create_socket!(sockets, tcp_rx_storage6, tcp_tx_storage6, tcp_handle6); create_socket!(sockets, tcp_rx_storage7, tcp_tx_storage7, tcp_handle7); let mut sessions = [ (http::Request::new(), tcp_handle0), (http::Request::new(), tcp_handle1), (http::Request::new(), tcp_handle2), (http::Request::new(), tcp_handle3), (http::Request::new(), tcp_handle4), (http::Request::new(), tcp_handle5), (http::Request::new(), tcp_handle6), (http::Request::new(), tcp_handle7), ]; let mut next_blink = 0; let mut next_info = 0; let mut led_state = true; let mut latch_reset_time = None; loop { let time = get_time(); for &mut(ref mut request, ref tcp_handle) in sessions.iter_mut() { let socket: &mut TcpSocket = sockets.get_mut(*tcp_handle).as_socket(); if !socket.is_open() { socket.listen(80).unwrap() } if socket.may_recv() { let request_status = { let data = socket.recv(TCP_RX_BUFFER_SIZE).unwrap(); request.input(data) }; match request_status { Ok(true) => { if socket.can_send() { pages::serve(socket, &request); } request.reset(); socket.close(); } Ok(false) => (), Err(err) => { println!("failed HTTP request: {}", err); request.reset(); socket.close(); } } } else if socket.may_send() { request.reset(); socket.close(); } } let timestamp_ms = 0; // TODO match iface.poll(&mut sockets, timestamp_ms) { Ok(()) | Err(Error::Exhausted) => (), Err(e) => println!("poll error: {}", e) } if time > next_blink { led_state = !led_state; next_blink = time + 1000; board::set_led(1, led_state); } if time >= next_info { let (anode, cathode, electrometer) = cortex_m::interrupt::free(|cs| { (LOOP_ANODE.borrow(cs).borrow().get_status(), LOOP_CATHODE.borrow(cs).borrow().get_status(), ELECTROMETER.borrow(cs).borrow().get_status()) }); println!(""); anode.debug_print(); cathode.debug_print(); electrometer.debug_print(); if cathode.fbi.is_some() && electrometer.ic.is_some() { let fbi = cathode.fbi.unwrap(); let ic = electrometer.ic.unwrap(); let pressure = ic/fbi/18.75154; println!("{:.1e} mbar", pressure); } next_info = next_info + 3000; } board::process_errors(); if board::error_latched() { match latch_reset_time { None => { println!("Protection latched"); latch_reset_time = Some(time + 10000); } Some(t) => if time > t { latch_reset_time = None; cortex_m::interrupt::free(|cs| { // reset PID loops as they have accumulated large errors // while the protection was active, which would cause // unnecessary overshoots. LOOP_ANODE.borrow(cs).borrow_mut().reset(); LOOP_CATHODE.borrow(cs).borrow_mut().reset(); board::reset_error(); }); println!("Protection reset"); } } } } } use tm4c129x::interrupt::ADC0SS0; extern fn adc0_ss0(_ctxt: ADC0SS0) { cortex_m::interrupt::free(|cs| { let adc0 = tm4c129x::ADC0.borrow(cs); if adc0.ostat.read().ov0().bit() { panic!("ADC FIFO overflowed") } adc0.isc.write(|w| w.in0().bit(true)); let ic_sample = adc0.ssfifo0.read().data().bits(); let fbi_sample = adc0.ssfifo0.read().data().bits(); let fv_sample = adc0.ssfifo0.read().data().bits(); let fd_sample = adc0.ssfifo0.read().data().bits(); let av_sample = adc0.ssfifo0.read().data().bits(); let fbv_sample = adc0.ssfifo0.read().data().bits(); let mut loop_anode = LOOP_ANODE.borrow(cs).borrow_mut(); let mut loop_cathode = LOOP_CATHODE.borrow(cs).borrow_mut(); let mut electrometer = ELECTROMETER.borrow(cs).borrow_mut(); loop_anode.adc_input(av_sample); loop_cathode.adc_input(fbi_sample, fd_sample, fv_sample, fbv_sample); electrometer.adc_input(ic_sample); let time = TIME.borrow(cs); time.set(time.get() + 1); }); } #[used] #[link_section = ".rodata.exceptions"] pub static EXCEPTIONS: ExceptionHandlers = ExceptionHandlers { ..cortex_m::exception::DEFAULT_HANDLERS }; #[used] #[link_section = ".rodata.interrupts"] pub static INTERRUPTS: InterruptHandlers = InterruptHandlers { ADC0SS0: adc0_ss0, ..tm4c129x::interrupt::DEFAULT_HANDLERS };