add systick interrupt for timekeeping

master
Astro 2019-09-08 01:24:20 +02:00
parent 152bc7b98b
commit e5529a8b94
3 changed files with 35 additions and 89 deletions

View File

@ -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))
}
}

View File

@ -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;

View File

@ -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();
}