Skip to content

Commit

Permalink
Get timers functional and add some error handling
Browse files Browse the repository at this point in the history
  • Loading branch information
ReeceStevens committed Dec 20, 2017
1 parent 9da6cfe commit a9bc1e8
Show file tree
Hide file tree
Showing 5 changed files with 29,971 additions and 30,991 deletions.
2 changes: 2 additions & 0 deletions f4/src/gpio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,9 @@ setup_pin!(PB10, 10, GPIOB, gpiob, gpioben, moder10, pupdr10, ospeedr10, ot10, b
setup_pin!(PB13, 13, GPIOB, gpiob, gpioben, moder13, pupdr13, ospeedr13, ot13, bs13, br13, afrh, afrh13);
setup_pin!(PB14, 14, GPIOB, gpiob, gpioben, moder14, pupdr14, ospeedr14, ot14, bs14, br14, afrh, afrh14);
setup_pin!(PC7, 7, GPIOC, gpioh, gpiocen, moder7, pupdr7, ospeedr7, ot7, bs7, br7, afrl, afrl7);
setup_pin!(PD12, 12, GPIOD, gpioh, gpioden, moder12, pupdr12, ospeedr12, ot12, bs12, br12, afrh, afrh12);
setup_pin!(PD13, 13, GPIOD, gpioh, gpioden, moder13, pupdr13, ospeedr13, ot13, bs13, br13, afrh, afrh13);
setup_pin!(PD14, 14, GPIOD, gpioh, gpioden, moder14, pupdr14, ospeedr14, ot14, bs14, br14, afrh, afrh14);
setup_pin!(PD15, 15, GPIOD, gpioh, gpioden, moder15, pupdr15, ospeedr15, ot15, bs15, br15, afrh, afrh15);

#[derive(Copy,Clone)]
Expand Down
10 changes: 5 additions & 5 deletions f4/src/logger.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use core::fmt;
use core::fmt::Write;
// use core::fmt;
// use core::fmt::Write;
pub use cortex_m_semihosting::hio as hio;

#[allow(non_camel_case_types)]
Expand Down Expand Up @@ -28,8 +28,8 @@ macro_rules! logger {
LogLevel::l_error => "ERROR",
LogLevel::l_fatal => "FATAL",
};
stdout.write_fmt(format_args!("{}{} |\t\t", log_color, log_name));
stdout.write_fmt(format_args!($($arg)*));
stdout.write_fmt(format_args!("\n"));
stdout.write_fmt(format_args!("{}{} |\t\t", log_color, log_name)).unwrap();
stdout.write_fmt(format_args!($($arg)*)).unwrap();
stdout.write_fmt(format_args!("\n")).unwrap();
};
}
55 changes: 32 additions & 23 deletions f4/src/spi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,29 @@ use gpio::{GPIO_AF, GPIOConfig};
use gpio::{PA5, PA6, PA7, PB10, PB14,
PC7, PB13, PA11, PA1};

pub enum SPI {
SPI1,
SPI2,
SPI3
use stm32f40x::i2s2ext;

pub struct Spi1<'a> {
dr: &'a i2s2ext::DR,
sr: &'a i2s2ext::SR
}

pub struct Spi1;
impl Spi1 {
fn config(spi1: &SPI1, gpioa: &GPIOA, rcc: &RCC) {
impl<'a> Spi1<'a> {
pub fn init(spi1: &SPI1, rcc: &RCC, gpioa: &GPIOA) {
rcc.apb2enr.write(|w| w.spi1en().set_bit());
let config = GPIOConfig::new_af(GPIO_AF::AF5_SPI1);
PA5.init(&config, rcc, gpioa);
PA6.init(&config, rcc, gpioa);
PA7.init(&config, rcc, gpioa);
PA5::init(config, rcc, gpioa);
PA6::init(config, rcc, gpioa);
PA7::init(config, rcc, gpioa);
channel_config(&spi1);
}
fn enable(spi1: &SPI1) {
pub fn get_reference(spi1: &SPI1) -> Spi1 {
Spi1 {
dr: &spi1.dr,
sr: &spi1.sr
}
}
pub fn enable(spi1: &SPI1) {
spi1.cr1.write(|w| w.spe().set_bit());
}
}
Expand All @@ -31,9 +37,9 @@ impl Spi2 {
fn config(&self, spi2: &SPI2, gpiob: &GPIOB, gpioc: &GPIOC, rcc: &RCC) {
rcc.apb1enr.write(|w| w.spi2en().set_bit());
let config = GPIOConfig::new_af(GPIO_AF::AF5_SPI1);
PC7.init(&config, rcc, gpioc);
PB14.init(&config, rcc, gpiob);
PB10.init(&config, rcc, gpiob);
PC7::init(config, rcc, gpioc);
PB14::init(config, rcc, gpiob);
PB10::init(config, rcc, gpiob);
channel_config(&spi2);
}
fn enable(&self, spi2: &SPI2) {
Expand All @@ -46,10 +52,10 @@ impl Spi4 {
fn config(&self, spi4: &SPI4, gpioa: &GPIOA, gpiob: &GPIOB, rcc: &RCC) {
rcc.apb2enr.write(|w| w.spi4en().set_bit());
let config = GPIOConfig::new_af(GPIO_AF::AF6_SPI4);
PB13.init(&config, rcc, gpiob);
PA11.init(&config, rcc, gpioa);
PB13::init(config, rcc, gpiob);
PA11::init(config, rcc, gpioa);
let config = GPIOConfig::new_af(GPIO_AF::AF5_SPI4);
PA1.init(&config, rcc, gpioa);
PA1::init(config, rcc, gpioa);
channel_config(&spi4);
}
fn enable(&self, spi4: &SPI4) {
Expand Down Expand Up @@ -87,10 +93,13 @@ fn channel_config(spi_channel: &SpiRegisters) {
unsafe { spi_channel.crcpr.write(|w| w.crcpoly().bits(7)); }
}

pub fn transfer(data: u8, spix: &SpiRegisters) -> u8 {
unsafe { spix.dr.write(|w| w.bits(data as u32)); }
while spix.sr.read().txe().bit_is_clear() {}; // Wait until transmit complete
while spix.sr.read().rxne().bit_is_clear() {}; // wait until receive complete
while spix.sr.read().bsy().bit_is_set() {}; // Wait until SPI is not busy
spix.dr.read().bits() as u8
// TODO: Generalize to all SPI peripherals
impl<'a> Spi1<'a> {
pub fn transfer(&self, data: u8) -> u8 {
unsafe { self.dr.write(|w| w.bits(data as u32)); }
while self.sr.read().txe().bit_is_clear() {}; // Wait until transmit complete
while self.sr.read().rxne().bit_is_clear() {}; // wait until receive complete
while self.sr.read().bsy().bit_is_set() {}; // Wait until SPI is not busy
self.dr.read().bits() as u8
}
}
46 changes: 26 additions & 20 deletions f4/src/timer.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
#![allow(dead_code)]
use core;
use core::result::Result::Err;
use stm32f40x::{tim1, RCC};
use stm32f40x::{TIM2, RCC};

pub struct TimerError;
pub type TimerResult<T> = core::result::Result<T, TimerError>;

const ABP1_CLOCK_SPEED: u32 = 42; // 42 MHz
const ABP1_CLOCK_SPEED: u32 = 21_000_000; // 21 MHz


// TODO: Only support timers 2-4 atm
Expand All @@ -16,54 +16,60 @@ pub enum TimerChannel {
TIM4
}

struct Timer<'a>(&'a tim1::RegisterBlock);
pub struct Timer<'a> {
timx: &'a TIM2
}

impl<'a> Timer<'a> {
pub fn init(&self, tc: &TimerChannel, rcc: &RCC, frequency: u32) {
let timx = self.0;
let ticks_per_timer = ABP1_CLOCK_SPEED / frequency;
pub fn init(&self, tc: TimerChannel, rcc: &RCC, frequency: u32) {
let timx = self.timx;
let ticks_per_timer: u32 = ABP1_CLOCK_SPEED / frequency;
let prescaler_value = (ticks_per_timer - 1) >> 16;
let autoreload_value = ticks_per_timer / (prescaler_value - 1);
match *tc {
let autoreload_value = ticks_per_timer / (prescaler_value + 1);
match tc {
TimerChannel::TIM2 => {
rcc.apb1enr.write(|w| w.tim2en().set_bit());
rcc.apb1enr.modify(|_, w| w.tim2en().set_bit());
},
TimerChannel::TIM3 => {
rcc.apb1enr.write(|w| w.tim3en().set_bit());
rcc.apb1enr.modify(|_, w| w.tim3en().set_bit());
},
TimerChannel::TIM4 => {
rcc.apb1enr.write(|w| w.tim4en().set_bit());
rcc.apb1enr.modify(|_, w| w.tim4en().set_bit());
}
};
unsafe {
timx.psc.write(|w| w.psc().bits(prescaler_value as u16));
timx.arr.write(|w| w.arr().bits(autoreload_value as u16));
timx.psc.modify(|_, w| w.psc().bits(prescaler_value as u16));
timx.arr.modify(|_, w| w.arr_l().bits(autoreload_value as u16));
timx.arr.modify(|_, w| w.arr_h().bits(0x0000 as u16));
}
timx.dier.write(|w| w.uie().set_bit());
timx.cr1.write(|w| w.opm().clear_bit()); // Set to continuous mode (is this necessary?)
timx.dier.modify(|_, w| w.uie().set_bit());
timx.cr1.modify(|_, w| w.opm().clear_bit());
}

pub fn new(timx: &TIM2) -> Timer {
Timer { timx: &timx }
}

/// Clears the update event flag
///
/// Returns `Err` if no update event has occurred
pub fn clear_update_flag(&self) -> TimerResult<()> {
let timx = self.0;

if timx.sr.read().uif().bit_is_clear() {
if self.timx.sr.read().uif().bit_is_clear() {
Err(TimerError {})
} else {
timx.sr.modify(|_, w| w.uif().clear_bit());
self.timx.sr.modify(|_, w| w.uif().clear_bit());
Ok(())
}
}

/// Resumes the timer count
pub fn resume(&self) {
self.0.cr1.modify(|_, w| w.cen().set_bit());
self.timx.cr1.modify(|_, w| w.cen().set_bit());
}

/// Pauses the timer
pub fn pause(&self) {
self.0.cr1.modify(|_, w| w.cen().clear_bit());
self.timx.cr1.modify(|_, w| w.cen().clear_bit());
}
}
Loading

0 comments on commit a9bc1e8

Please sign in to comment.