forked from M-Labs/ionpak-thermostat
add systick interrupt for timekeeping
This commit is contained in:
parent
152bc7b98b
commit
e5529a8b94
|
@ -1,76 +0,0 @@
|
||||||
use embedded_hal::blocking::delay::{DelayMs, DelayUs};
|
|
||||||
use cortex_m::peripheral::syst::SystClkSource;
|
|
||||||
use cortex_m::peripheral::SYST;
|
|
||||||
use tm4c129x::CorePeripherals;
|
|
||||||
|
|
||||||
/// precision internal oscillator
|
|
||||||
const PIOSC: u32 = 16_000_000;
|
|
||||||
|
|
||||||
pub struct Delay {
|
|
||||||
syst: SYST,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Delay {
|
|
||||||
/// unsafe: must only be used once to avoid concurrent use of systick
|
|
||||||
pub unsafe fn new() -> Self {
|
|
||||||
let mut syst = CorePeripherals::steal().SYST;
|
|
||||||
// PIOSC
|
|
||||||
syst.set_clock_source(SystClkSource::External);
|
|
||||||
syst.disable_interrupt();
|
|
||||||
Delay { syst }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl DelayMs<u32> for Delay {
|
|
||||||
fn delay_ms(&mut self, ms: u32) {
|
|
||||||
self.delay_us(ms * 1_000);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl DelayMs<u16> for Delay {
|
|
||||||
fn delay_ms(&mut self, ms: u16) {
|
|
||||||
self.delay_ms(u32::from(ms));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl DelayMs<u8> for Delay {
|
|
||||||
fn delay_ms(&mut self, ms: u8) {
|
|
||||||
self.delay_ms(u32::from(ms));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl DelayUs<u32> for Delay {
|
|
||||||
fn delay_us(&mut self, us: u32) {
|
|
||||||
// The SysTick Reload Value register supports values between 1 and 0x00FFFFFF.
|
|
||||||
const MAX_RVR: u32 = 0x00FF_FFFF;
|
|
||||||
|
|
||||||
let mut total_rvr = us * (PIOSC / 1_000_000);
|
|
||||||
|
|
||||||
while total_rvr != 0 {
|
|
||||||
let current_rvr = total_rvr.min(MAX_RVR);
|
|
||||||
|
|
||||||
self.syst.set_reload(current_rvr);
|
|
||||||
self.syst.clear_current();
|
|
||||||
self.syst.enable_counter();
|
|
||||||
|
|
||||||
// Update the tracking variable while we are waiting...
|
|
||||||
total_rvr -= current_rvr;
|
|
||||||
|
|
||||||
while !self.syst.has_wrapped() {}
|
|
||||||
|
|
||||||
self.syst.disable_counter();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl DelayUs<u16> for Delay {
|
|
||||||
fn delay_us(&mut self, us: u16) {
|
|
||||||
self.delay_us(u32::from(us))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl DelayUs<u8> for Delay {
|
|
||||||
fn delay_us(&mut self, us: u8) {
|
|
||||||
self.delay_us(u32::from(us))
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -3,7 +3,6 @@ use tm4c129x;
|
||||||
|
|
||||||
pub mod gpio;
|
pub mod gpio;
|
||||||
pub mod softspi;
|
pub mod softspi;
|
||||||
pub mod delay;
|
|
||||||
|
|
||||||
|
|
||||||
const UART_DIV: u32 = (((/*sysclk*/120_000_000 * 8) / /*baud*/115200) + 1) / 2;
|
const UART_DIV: u32 = (((/*sysclk*/120_000_000 * 8) / /*baud*/115200) + 1) / 2;
|
||||||
|
|
|
@ -2,9 +2,9 @@
|
||||||
#![no_std]
|
#![no_std]
|
||||||
#![no_main]
|
#![no_main]
|
||||||
|
|
||||||
use cortex_m_rt::entry;
|
use cortex_m_rt::{entry, exception};
|
||||||
use core::fmt::{self, Write};
|
use core::fmt::{self, Write};
|
||||||
use embedded_hal::blocking::delay::DelayUs;
|
use cortex_m::peripheral::{SYST, syst::SystClkSource};
|
||||||
use smoltcp::time::Instant;
|
use smoltcp::time::Instant;
|
||||||
use smoltcp::wire::{IpCidr, IpAddress, EthernetAddress};
|
use smoltcp::wire::{IpCidr, IpAddress, EthernetAddress};
|
||||||
use smoltcp::iface::{NeighborCache, EthernetInterfaceBuilder};
|
use smoltcp::iface::{NeighborCache, EthernetInterfaceBuilder};
|
||||||
|
@ -76,6 +76,7 @@ fn main() -> ! {
|
||||||
writeln!(stdout, "ionpak boot").unwrap();
|
writeln!(stdout, "ionpak boot").unwrap();
|
||||||
board::init();
|
board::init();
|
||||||
writeln!(stdout, "board initialized").unwrap();
|
writeln!(stdout, "board initialized").unwrap();
|
||||||
|
init_systick();
|
||||||
|
|
||||||
println!(r#"
|
println!(r#"
|
||||||
_ _
|
_ _
|
||||||
|
@ -87,7 +88,6 @@ fn main() -> ! {
|
||||||
| |
|
| |
|
||||||
|_|
|
|_|
|
||||||
"#);
|
"#);
|
||||||
let mut delay = unsafe { board::delay::Delay::new() };
|
|
||||||
// CSn
|
// CSn
|
||||||
let pb4 = board::gpio::PB4.into_output();
|
let pb4 = board::gpio::PB4.into_output();
|
||||||
// SCLK
|
// SCLK
|
||||||
|
@ -97,7 +97,6 @@ fn main() -> ! {
|
||||||
// MISO
|
// MISO
|
||||||
let pe5 = board::gpio::PE5.into_input();
|
let pe5 = board::gpio::PE5.into_input();
|
||||||
// max 2 MHz = 0.5 us
|
// max 2 MHz = 0.5 us
|
||||||
// let mut delay_fn = || delay.delay_us(1u32);
|
|
||||||
let mut delay_fn = || for _ in 0..10 { cortex_m::asm::nop(); };
|
let mut delay_fn = || for _ in 0..10 { cortex_m::asm::nop(); };
|
||||||
let spi = board::softspi::SyncSoftSpi::new(
|
let spi = board::softspi::SyncSoftSpi::new(
|
||||||
board::softspi::SoftSpi::new(pb5, pe4, pe5),
|
board::softspi::SoftSpi::new(pb5, pe4, pe5),
|
||||||
|
@ -189,7 +188,8 @@ fn main() -> ! {
|
||||||
.and_then(|channel|
|
.and_then(|channel|
|
||||||
channel.map(|channel|
|
channel.map(|channel|
|
||||||
adc.read_data().map(|new_data| {
|
adc.read_data().map(|new_data| {
|
||||||
data = Some(Ok((channel, new_data)));
|
let now = get_time();
|
||||||
|
data = Some((now, Ok((channel, new_data))));
|
||||||
for p in socket_pending.iter_mut() {
|
for p in socket_pending.iter_mut() {
|
||||||
*p = true;
|
*p = true;
|
||||||
}
|
}
|
||||||
|
@ -197,7 +197,8 @@ fn main() -> ! {
|
||||||
).unwrap_or(Ok(()))
|
).unwrap_or(Ok(()))
|
||||||
)
|
)
|
||||||
.map_err(|e| {
|
.map_err(|e| {
|
||||||
data = Some(Err(e));
|
let now = get_time();
|
||||||
|
data = Some((now, Err(e)));
|
||||||
for p in socket_pending.iter_mut() {
|
for p in socket_pending.iter_mut() {
|
||||||
*p = true;
|
*p = true;
|
||||||
}
|
}
|
||||||
|
@ -211,14 +212,14 @@ fn main() -> ! {
|
||||||
|
|
||||||
if socket.may_send() && *pending {
|
if socket.may_send() && *pending {
|
||||||
match &data {
|
match &data {
|
||||||
Some(Ok((channel, input))) => {
|
Some((time, Ok((channel, input)))) => {
|
||||||
let _ = writeln!(socket, "channel={} input={}\r", channel, input);
|
let _ = writeln!(socket, "t={} channel={} input={}\r", time, channel, input);
|
||||||
}
|
}
|
||||||
Some(Err(ad7172::AdcError::ChecksumMismatch(Some(expected), Some(input)))) => {
|
Some((time, Err(ad7172::AdcError::ChecksumMismatch(Some(expected), Some(input))))) => {
|
||||||
let _ = writeln!(socket, "checksum_expected={:02X} checksum_input={:02X}\r", expected, input);
|
let _ = writeln!(socket, "t={} checksum_expected={:02X} checksum_input={:02X}\r", time, expected, input);
|
||||||
}
|
}
|
||||||
Some(Err(e)) => {
|
Some((time, Err(e))) => {
|
||||||
let _ = writeln!(socket, "adc_error={:?}\r", e);
|
let _ = writeln!(socket, "t={} adc_error={:?}\r", time, e);
|
||||||
}
|
}
|
||||||
None => {}
|
None => {}
|
||||||
}
|
}
|
||||||
|
@ -232,3 +233,25 @@ fn main() -> ! {
|
||||||
time += 1;
|
time += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const SYSTICK_RATE: u32 = 1000;
|
||||||
|
static mut TIME: u32 = 0;
|
||||||
|
|
||||||
|
pub fn get_time() -> u32 {
|
||||||
|
unsafe { TIME }
|
||||||
|
}
|
||||||
|
|
||||||
|
#[exception]
|
||||||
|
fn SysTick() {
|
||||||
|
unsafe { TIME += 1000 / SYSTICK_RATE; }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn init_systick() {
|
||||||
|
#[allow(mutable_transmutes)]
|
||||||
|
let syst: &mut SYST = unsafe { core::mem::transmute(&*SYST::ptr()) };
|
||||||
|
syst.set_clock_source(SystClkSource::Core);
|
||||||
|
syst.set_reload(100 * SYST::get_ticks_per_10ms() / SYSTICK_RATE);
|
||||||
|
syst.clear_current();
|
||||||
|
syst.enable_interrupt();
|
||||||
|
syst.enable_counter();
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue