ionpak-thermostat/firmware/src/main.rs

235 lines
8.2 KiB
Rust
Raw Normal View History

#![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
2019-09-08 07:54:51 +08:00
use cortex_m_rt::entry;
use core::fmt::{self, Write};
2018-03-26 19:37:14 +08:00
use smoltcp::time::Instant;
2019-08-21 17:31:51 +08:00
use smoltcp::wire::{IpCidr, IpAddress, EthernetAddress};
use smoltcp::iface::{NeighborCache, EthernetInterfaceBuilder};
use smoltcp::socket::{SocketSet, TcpSocket, TcpSocketBuffer};
2019-09-02 05:56:27 +08:00
use cortex_m_semihosting::hio;
2017-05-04 17:35:26 +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-09 15:57:54 +08:00
mod board;
2019-09-08 07:54:51 +08:00
use self::board::{gpio::Gpio, systick::get_time};
2017-08-02 00:33:33 +08:00
mod ethmac;
2019-08-08 08:08:14 +08:00
mod ad7172;
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(())
}
}
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);
)
}
#[entry]
2018-08-29 03:57:17 +08:00
fn main() -> ! {
2019-09-02 05:56:27 +08:00
let mut stdout = hio::hstdout().unwrap();
2019-09-02 06:01:18 +08:00
writeln!(stdout, "ionpak boot").unwrap();
2017-05-09 15:57:54 +08:00
board::init();
2019-09-02 06:01:18 +08:00
writeln!(stdout, "board initialized").unwrap();
2017-05-04 19:42:22 +08:00
println!(r#"
_ _
(_) | |
_ ___ _ __ _ __ __ _| |
| |/ _ \| '_ \| '_ \ / _` | |/ /
| | (_) | | | | |_) | (_| | <
|_|\___/|_| |_| .__/ \__,_|_|\_\
| |
|_|
"#);
2019-08-08 07:57:30 +08:00
// CSn
2019-08-08 06:54:37 +08:00
let pb4 = board::gpio::PB4.into_output();
// SCLK
let pb5 = board::gpio::PB5.into_output();
// MOSI
let pe4 = board::gpio::PE4.into_output();
// MISO
let pe5 = board::gpio::PE5.into_input();
2019-09-02 05:56:45 +08:00
// max 2 MHz = 0.5 us
2019-09-08 06:47:41 +08:00
let mut delay_fn = || for _ in 0..10 { cortex_m::asm::nop(); };
2019-08-08 06:54:37 +08:00
let spi = board::softspi::SyncSoftSpi::new(
2019-08-08 08:08:14 +08:00
board::softspi::SoftSpi::new(pb5, pe4, pe5),
&mut delay_fn
2019-08-08 06:54:37 +08:00
);
let mut adc = ad7172::Adc::new(spi, pb4).unwrap();
2019-09-02 05:56:45 +08:00
loop {
let r = adc.identify();
match r {
2019-09-08 05:29:26 +08:00
Err(e) =>
writeln!(stdout, "Cannot identify ADC: {:?}", e).unwrap(),
Ok(id) if id & 0xFFF0 == 0x00D0 => {
2019-09-02 06:01:18 +08:00
writeln!(stdout, "ADC id: {:04X}", id).unwrap();
2019-09-02 05:56:45 +08:00
break;
}
2019-09-08 05:29:26 +08:00
Ok(id) =>
writeln!(stdout, "Corrupt ADC id: {:04X}", id).unwrap(),
};
}
2019-09-08 06:47:14 +08:00
writeln!(stdout, "AD7172: setting checksum mode").unwrap();
adc.set_checksum_mode(ad7172::ChecksumMode::Crc).unwrap();
2019-09-08 05:29:26 +08:00
loop {
let r = adc.identify();
match r {
Err(e) =>
writeln!(stdout, "Cannot identify ADC: {:?}", e).unwrap(),
Ok(id) if id & 0xFFF0 == 0x00D0 => {
writeln!(stdout, "ADC id: {:04X}", id).unwrap();
break;
}
Ok(id) =>
2019-09-02 05:56:45 +08:00
writeln!(stdout, "Corrupt ADC id: {:04X}", id).unwrap(),
};
}
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]);
}
let mut ip_addrs = [IpCidr::new(IpAddress::v4(192, 168, 1, 26), 24)];
println!("MAC {} IP {}", hardware_addr, ip_addrs[0]);
let mut neighbor_cache_storage = [None; 8];
let neighbor_cache = NeighborCache::new(&mut neighbor_cache_storage[..]);
let mut device = ethmac::Device::new();
unsafe { device.init(hardware_addr) };
let mut iface = EthernetInterfaceBuilder::new(&mut device)
.ethernet_addr(hardware_addr)
.neighbor_cache(neighbor_cache)
.ip_addrs(&mut ip_addrs[..])
.finalize();
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 handles = [
tcp_handle0,
tcp_handle1,
tcp_handle2,
tcp_handle3,
tcp_handle4,
tcp_handle5,
tcp_handle6,
tcp_handle7,
];
2019-09-08 08:43:01 +08:00
let mut read_times = [0, 0];
2019-09-08 05:29:26 +08:00
let mut data = None;
// if a socket has sent the latest data
let mut socket_pending = [false; 8];
2017-05-06 12:33:38 +08:00
loop {
let _ = adc.data_ready()
2019-09-08 05:29:26 +08:00
.and_then(|channel|
channel.map(|channel|
adc.read_data().map(|new_data| {
2019-09-08 07:24:20 +08:00
let now = get_time();
2019-09-08 08:43:01 +08:00
read_times[0] = read_times[1];
read_times[1] = now;
2019-09-08 07:24:20 +08:00
data = Some((now, Ok((channel, new_data))));
2019-09-08 05:29:26 +08:00
for p in socket_pending.iter_mut() {
*p = true;
}
})
2019-09-08 05:29:26 +08:00
).unwrap_or(Ok(()))
)
.map_err(|e| {
2019-09-08 07:24:20 +08:00
let now = get_time();
data = Some((now, Err(e)));
2019-09-08 05:29:26 +08:00
for p in socket_pending.iter_mut() {
*p = true;
}
});
2019-08-21 17:31:51 +08:00
for (&tcp_handle, pending) in handles.iter().zip(socket_pending.iter_mut()) {
let socket = &mut *sockets.get::<TcpSocket>(tcp_handle);
if !socket.is_open() {
socket.listen(23).unwrap()
}
if socket.may_send() && *pending {
2019-09-08 05:29:26 +08:00
match &data {
2019-09-08 07:24:20 +08:00
Some((time, Ok((channel, input)))) => {
2019-09-08 08:43:01 +08:00
let interval = read_times[1] - read_times[0];
let _ = writeln!(socket, "t={}-{} channel={} input={}\r", time, interval, channel, input);
2019-09-08 05:29:26 +08:00
}
2019-09-08 07:24:20 +08:00
Some((time, Err(ad7172::AdcError::ChecksumMismatch(Some(expected), Some(input))))) => {
let _ = writeln!(socket, "t={} checksum_expected={:02X} checksum_input={:02X}\r", time, expected, input);
2019-09-08 05:29:26 +08:00
}
2019-09-08 07:24:20 +08:00
Some((time, Err(e))) => {
let _ = writeln!(socket, "t={} adc_error={:?}\r", time, e);
2019-09-08 05:29:26 +08:00
}
None => {}
}
*pending = false;
}
}
match iface.poll(&mut sockets, Instant::from_millis((get_time() / 1000) as i64)) {
2017-09-05 17:26:23 +08:00
Ok(_) => (),
Err(e) => println!("poll error: {}", e)
}
2017-05-06 12:33:38 +08:00
}
2017-05-04 17:35:26 +08:00
}