2019-02-06 17:19:28 +08:00
|
|
|
#![feature(const_fn)]
|
2017-05-04 17:35:26 +08:00
|
|
|
#![no_std]
|
2018-08-29 03:57:17 +08:00
|
|
|
#![no_main]
|
2017-05-04 17:35:26 +08:00
|
|
|
|
2018-08-29 03:57:17 +08:00
|
|
|
extern crate libm;
|
2017-05-04 17:35:26 +08:00
|
|
|
extern crate cortex_m;
|
2018-08-29 03:57:17 +08:00
|
|
|
#[macro_use]
|
2017-05-04 17:35:26 +08:00
|
|
|
extern crate cortex_m_rt;
|
2017-08-06 12:59:30 +08:00
|
|
|
#[macro_use(interrupt)]
|
2017-05-04 17:35:26 +08:00
|
|
|
extern crate tm4c129x;
|
2017-08-02 00:33:33 +08:00
|
|
|
extern crate smoltcp;
|
2018-03-27 18:16:11 +08:00
|
|
|
extern crate crc;
|
2019-07-31 00:25:35 +08:00
|
|
|
extern crate embedded_hal;
|
2019-08-01 06:59:29 +08:00
|
|
|
extern crate nb;
|
2017-05-04 17:35:26 +08:00
|
|
|
|
2017-05-06 17:17:41 +08:00
|
|
|
use core::cell::{Cell, RefCell};
|
2017-05-09 13:16:00 +08:00
|
|
|
use core::fmt;
|
2017-05-06 17:17:41 +08:00
|
|
|
use cortex_m::interrupt::Mutex;
|
2018-03-26 19:37:14 +08:00
|
|
|
use smoltcp::time::Instant;
|
2017-08-08 11:05:09 +08:00
|
|
|
use smoltcp::wire::EthernetAddress;
|
2018-01-26 21:03:04 +08:00
|
|
|
use smoltcp::iface::{NeighborCache, EthernetInterfaceBuilder};
|
|
|
|
use smoltcp::socket::{SocketSet, TcpSocket, TcpSocketBuffer};
|
2017-05-04 17:35:26 +08:00
|
|
|
|
2017-05-11 14:55:00 +08:00
|
|
|
#[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)*));
|
|
|
|
}
|
|
|
|
|
2018-08-29 03:57:17 +08:00
|
|
|
#[no_mangle] // https://github.com/rust-lang/rust/issues/{38281,51647}
|
|
|
|
#[panic_handler]
|
|
|
|
pub fn panic_fmt(info: &core::panic::PanicInfo) -> ! {
|
|
|
|
println!("{}", info);
|
2017-08-06 19:52:11 +08:00
|
|
|
loop {}
|
|
|
|
}
|
|
|
|
|
2017-05-11 14:55:00 +08:00
|
|
|
#[macro_use]
|
2017-05-09 15:57:54 +08:00
|
|
|
mod board;
|
2017-08-07 16:13:29 +08:00
|
|
|
mod eeprom;
|
2017-08-07 23:57:29 +08:00
|
|
|
mod config;
|
2017-08-02 00:33:33 +08:00
|
|
|
mod ethmac;
|
2017-05-06 17:17:41 +08:00
|
|
|
|
2017-08-06 11:37:24 +08:00
|
|
|
static ADC_IRQ_COUNT: Mutex<Cell<u64>> = Mutex::new(Cell::new(0));
|
2017-05-11 14:55:00 +08:00
|
|
|
|
2017-08-06 11:37:24 +08:00
|
|
|
fn get_time_ms() -> u64 {
|
|
|
|
let adc_irq_count = cortex_m::interrupt::free(|cs| {
|
|
|
|
ADC_IRQ_COUNT.borrow(cs).get()
|
|
|
|
});
|
2017-08-07 11:25:39 +08:00
|
|
|
adc_irq_count*24/125
|
2017-05-11 14:55:00 +08:00
|
|
|
}
|
2017-05-06 17:17:41 +08:00
|
|
|
|
2017-05-09 13:16:00 +08:00
|
|
|
pub struct UART0;
|
|
|
|
|
|
|
|
impl fmt::Write for UART0 {
|
|
|
|
fn write_str(&mut self, s: &str) -> Result<(), fmt::Error> {
|
2018-08-29 03:57:17 +08:00
|
|
|
let uart_0 = unsafe { &*tm4c129x::UART0::ptr() };
|
2017-05-09 13:16:00 +08:00
|
|
|
for c in s.bytes() {
|
2018-08-29 03:57:17 +08:00
|
|
|
while uart_0.fr.read().txff().bit() {}
|
|
|
|
uart_0.dr.write(|w| w.data().bits(c))
|
2017-05-09 13:16:00 +08:00
|
|
|
}
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-08-05 15:51:54 +08:00
|
|
|
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);
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2019-02-06 17:19:28 +08:00
|
|
|
#[entry]
|
2018-08-29 03:57:17 +08:00
|
|
|
fn main() -> ! {
|
2017-05-09 15:57:54 +08:00
|
|
|
board::init();
|
2017-05-04 19:42:22 +08:00
|
|
|
|
2017-08-07 23:57:29 +08:00
|
|
|
let mut config = config::Config::new();
|
|
|
|
eeprom::init();
|
2019-07-30 23:02:05 +08:00
|
|
|
/*if button_pressed {
|
2017-08-08 12:19:05 +08:00
|
|
|
config.save();
|
|
|
|
} else {
|
|
|
|
config.load();
|
2019-07-30 23:02:05 +08:00
|
|
|
}*/
|
2017-08-07 23:57:29 +08:00
|
|
|
|
2017-05-11 14:55:00 +08:00
|
|
|
println!(r#"
|
|
|
|
_ _
|
|
|
|
(_) | |
|
|
|
|
_ ___ _ __ _ __ __ _| |
|
|
|
|
| |/ _ \| '_ \| '_ \ / _` | |/ /
|
|
|
|
| | (_) | | | | |_) | (_| | <
|
|
|
|
|_|\___/|_| |_| .__/ \__,_|_|\_\
|
|
|
|
| |
|
|
|
|
|_|
|
2017-08-05 15:51:54 +08:00
|
|
|
"#);
|
|
|
|
|
2017-08-07 11:18:19 +08:00
|
|
|
let mut hardware_addr = EthernetAddress(board::get_mac_address());
|
|
|
|
if hardware_addr.is_multicast() {
|
|
|
|
println!("programmed MAC address is invalid, using default");
|
|
|
|
hardware_addr = EthernetAddress([0x10, 0xE2, 0xD5, 0x00, 0x03, 0x00]);
|
|
|
|
}
|
2018-01-26 21:03:04 +08:00
|
|
|
let mut ip_addrs = [config.ip];
|
|
|
|
println!("MAC {} IP {}", hardware_addr, ip_addrs[0]);
|
|
|
|
let mut neighbor_cache_storage = [None; 8];
|
|
|
|
let neighbor_cache = NeighborCache::new(&mut neighbor_cache_storage[..]);
|
2018-03-26 20:35:28 +08:00
|
|
|
let mut device = ethmac::Device::new();
|
|
|
|
unsafe { device.init(hardware_addr) };
|
|
|
|
let mut iface = EthernetInterfaceBuilder::new(&mut device)
|
2018-01-26 21:03:04 +08:00
|
|
|
.ethernet_addr(hardware_addr)
|
|
|
|
.neighbor_cache(neighbor_cache)
|
|
|
|
.ip_addrs(&mut ip_addrs[..])
|
|
|
|
.finalize();
|
2017-08-05 15:51:54 +08:00
|
|
|
|
|
|
|
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);
|
|
|
|
|
2019-07-30 21:35:56 +08:00
|
|
|
/*let mut sessions = [
|
2017-08-05 15:51:54 +08:00
|
|
|
(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),
|
2019-07-30 21:35:56 +08:00
|
|
|
];*/
|
2017-05-11 14:55:00 +08:00
|
|
|
|
2019-07-30 23:02:05 +08:00
|
|
|
/*board::set_hv_pwm(board::PWM_LOAD / 2);
|
2019-07-30 21:35:56 +08:00
|
|
|
board::set_fv_pwm(board::PWM_LOAD / 2);
|
2019-07-30 23:02:05 +08:00
|
|
|
board::set_fbv_pwm(board::PWM_LOAD / 2);*/
|
2017-08-06 19:06:47 +08:00
|
|
|
board::start_adc();
|
|
|
|
|
2019-07-30 23:02:05 +08:00
|
|
|
let mut fast_blink_count = 0;
|
2017-05-11 14:55:00 +08:00
|
|
|
let mut next_blink = 0;
|
|
|
|
let mut led_state = true;
|
|
|
|
let mut latch_reset_time = None;
|
2017-05-06 12:33:38 +08:00
|
|
|
loop {
|
2017-08-06 11:37:24 +08:00
|
|
|
let time = get_time_ms();
|
2017-05-11 14:55:00 +08:00
|
|
|
|
2019-07-30 21:35:56 +08:00
|
|
|
/*for &mut(ref mut request, tcp_handle) in sessions.iter_mut() {
|
2018-01-26 21:03:04 +08:00
|
|
|
let socket = &mut *sockets.get::<TcpSocket>(tcp_handle);
|
2017-08-05 15:51:54 +08:00
|
|
|
if !socket.is_open() {
|
|
|
|
socket.listen(80).unwrap()
|
|
|
|
}
|
|
|
|
|
|
|
|
if socket.may_recv() {
|
2018-01-26 21:03:04 +08:00
|
|
|
match socket.recv(|data| (data.len(), request.input(data))).unwrap() {
|
2017-08-05 15:51:54 +08:00
|
|
|
Ok(true) => {
|
|
|
|
if socket.can_send() {
|
2017-08-08 11:05:09 +08:00
|
|
|
pages::serve(socket, &request, &mut config, &LOOP_ANODE, &LOOP_CATHODE, &ELECTROMETER);
|
2017-08-05 15:51:54 +08:00
|
|
|
}
|
|
|
|
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();
|
|
|
|
}
|
2019-07-30 21:35:56 +08:00
|
|
|
}*/
|
2018-03-26 19:37:14 +08:00
|
|
|
match iface.poll(&mut sockets, Instant::from_millis(time as i64)) {
|
2017-09-05 17:26:23 +08:00
|
|
|
Ok(_) => (),
|
2017-08-05 15:51:54 +08:00
|
|
|
Err(e) => println!("poll error: {}", e)
|
|
|
|
}
|
|
|
|
|
|
|
|
board::process_errors();
|
2017-05-11 14:55:00 +08:00
|
|
|
if board::error_latched() {
|
|
|
|
match latch_reset_time {
|
|
|
|
None => {
|
|
|
|
println!("Protection latched");
|
2017-08-06 11:37:24 +08:00
|
|
|
latch_reset_time = Some(time + 5000);
|
2017-05-11 14:55:00 +08:00
|
|
|
}
|
|
|
|
Some(t) => if time > t {
|
|
|
|
latch_reset_time = None;
|
|
|
|
cortex_m::interrupt::free(|cs| {
|
2017-05-11 23:15:01 +08:00
|
|
|
board::reset_error();
|
2017-05-11 14:55:00 +08:00
|
|
|
});
|
|
|
|
println!("Protection reset");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2017-05-06 12:33:38 +08:00
|
|
|
}
|
2017-05-04 17:35:26 +08:00
|
|
|
}
|
|
|
|
|
2017-08-06 12:59:30 +08:00
|
|
|
interrupt!(ADC0SS0, adc0_ss0);
|
|
|
|
fn adc0_ss0() {
|
2017-05-05 19:31:12 +08:00
|
|
|
cortex_m::interrupt::free(|cs| {
|
2018-08-29 03:57:17 +08:00
|
|
|
let adc0 = unsafe { &*tm4c129x::ADC0::ptr() };
|
2017-05-05 19:31:12 +08:00
|
|
|
if adc0.ostat.read().ov0().bit() {
|
|
|
|
panic!("ADC FIFO overflowed")
|
|
|
|
}
|
2017-05-07 00:00:01 +08:00
|
|
|
adc0.isc.write(|w| w.in0().bit(true));
|
2017-05-05 19:31:12 +08:00
|
|
|
|
2017-05-11 14:55:00 +08:00
|
|
|
let ic_sample = adc0.ssfifo0.read().data().bits();
|
2017-05-09 15:57:54 +08:00
|
|
|
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();
|
|
|
|
|
2017-08-06 11:37:24 +08:00
|
|
|
let adc_irq_count = ADC_IRQ_COUNT.borrow(cs);
|
|
|
|
adc_irq_count.set(adc_irq_count.get() + 1);
|
2017-05-10 00:10:52 +08:00
|
|
|
});
|
2017-05-05 19:31:12 +08:00
|
|
|
}
|