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 softspi;
|
||||
pub mod delay;
|
||||
|
||||
|
||||
const UART_DIV: u32 = (((/*sysclk*/120_000_000 * 8) / /*baud*/115200) + 1) / 2;
|
||||
|
|
|
@ -2,9 +2,9 @@
|
|||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use cortex_m_rt::entry;
|
||||
use cortex_m_rt::{entry, exception};
|
||||
use core::fmt::{self, Write};
|
||||
use embedded_hal::blocking::delay::DelayUs;
|
||||
use cortex_m::peripheral::{SYST, syst::SystClkSource};
|
||||
use smoltcp::time::Instant;
|
||||
use smoltcp::wire::{IpCidr, IpAddress, EthernetAddress};
|
||||
use smoltcp::iface::{NeighborCache, EthernetInterfaceBuilder};
|
||||
|
@ -76,6 +76,7 @@ fn main() -> ! {
|
|||
writeln!(stdout, "ionpak boot").unwrap();
|
||||
board::init();
|
||||
writeln!(stdout, "board initialized").unwrap();
|
||||
init_systick();
|
||||
|
||||
println!(r#"
|
||||
_ _
|
||||
|
@ -87,7 +88,6 @@ fn main() -> ! {
|
|||
| |
|
||||
|_|
|
||||
"#);
|
||||
let mut delay = unsafe { board::delay::Delay::new() };
|
||||
// CSn
|
||||
let pb4 = board::gpio::PB4.into_output();
|
||||
// SCLK
|
||||
|
@ -97,7 +97,6 @@ fn main() -> ! {
|
|||
// MISO
|
||||
let pe5 = board::gpio::PE5.into_input();
|
||||
// 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 spi = board::softspi::SyncSoftSpi::new(
|
||||
board::softspi::SoftSpi::new(pb5, pe4, pe5),
|
||||
|
@ -189,7 +188,8 @@ fn main() -> ! {
|
|||
.and_then(|channel|
|
||||
channel.map(|channel|
|
||||
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() {
|
||||
*p = true;
|
||||
}
|
||||
|
@ -197,7 +197,8 @@ fn main() -> ! {
|
|||
).unwrap_or(Ok(()))
|
||||
)
|
||||
.map_err(|e| {
|
||||
data = Some(Err(e));
|
||||
let now = get_time();
|
||||
data = Some((now, Err(e)));
|
||||
for p in socket_pending.iter_mut() {
|
||||
*p = true;
|
||||
}
|
||||
|
@ -211,14 +212,14 @@ fn main() -> ! {
|
|||
|
||||
if socket.may_send() && *pending {
|
||||
match &data {
|
||||
Some(Ok((channel, input))) => {
|
||||
let _ = writeln!(socket, "channel={} input={}\r", channel, input);
|
||||
Some((time, Ok((channel, input)))) => {
|
||||
let _ = writeln!(socket, "t={} channel={} input={}\r", time, channel, input);
|
||||
}
|
||||
Some(Err(ad7172::AdcError::ChecksumMismatch(Some(expected), Some(input)))) => {
|
||||
let _ = writeln!(socket, "checksum_expected={:02X} checksum_input={:02X}\r", expected, input);
|
||||
Some((time, Err(ad7172::AdcError::ChecksumMismatch(Some(expected), Some(input))))) => {
|
||||
let _ = writeln!(socket, "t={} checksum_expected={:02X} checksum_input={:02X}\r", time, expected, input);
|
||||
}
|
||||
Some(Err(e)) => {
|
||||
let _ = writeln!(socket, "adc_error={:?}\r", e);
|
||||
Some((time, Err(e))) => {
|
||||
let _ = writeln!(socket, "t={} adc_error={:?}\r", time, e);
|
||||
}
|
||||
None => {}
|
||||
}
|
||||
|
@ -232,3 +233,25 @@ fn main() -> ! {
|
|||
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