Skip to content
Snippets Groups Projects
Commit 768b9b90 authored by Brandon Edens's avatar Brandon Edens
Browse files

Update dependencies and add implementation of HAL for serial.

parent ac6a827d
No related branches found
No related tags found
No related merge requests found
...@@ -9,9 +9,19 @@ name = "f3" ...@@ -9,9 +9,19 @@ name = "f3"
repository = "https://github.com/japaric/f3" repository = "https://github.com/japaric/f3"
version = "0.5.0" version = "0.5.0"
[dependencies]
static-ref = "0.2.0"
[dependencies.cast] [dependencies.cast]
default-features = false default-features = false
version = "0.2.0" version = "0.2.2"
[dependencies.embedded-hal]
git = "https://github.com/japaric/embedded-hal"
rev = "7d904f515d15fd5fe7ea34e18820ea83e2651fa2"
[dependencies.nb]
git = "https://github.com/japaric/nb"
[dependencies.stm32f30x] [dependencies.stm32f30x]
features = ["rt"] features = ["rt"]
......
...@@ -7,11 +7,14 @@ ...@@ -7,11 +7,14 @@
extern crate cortex_m_rtfm as rtfm; extern crate cortex_m_rtfm as rtfm;
extern crate f3; extern crate f3;
use f3::serial::Serial; use f3::prelude::*;
use f3::Serial;
use f3::serial::Event;
use f3::time::Hertz;
use rtfm::{app, Threshold}; use rtfm::{app, Threshold};
// CONFIGURATION // CONFIGURATION
const BAUD_RATE: u32 = 115_200; // bits per second const BAUD_RATE: Hertz = Hertz(115_200);
// TASKS & RESOURCES // TASKS & RESOURCES
app! { app! {
...@@ -27,9 +30,10 @@ app! { ...@@ -27,9 +30,10 @@ app! {
// INITIALIZATION PHASE // INITIALIZATION PHASE
fn init(p: init::Peripherals) { fn init(p: init::Peripherals) {
let serial = Serial(&p.USART1); let serial = Serial(p.USART1);
serial.init(&p.GPIOA, &p.RCC, BAUD_RATE); serial.init(BAUD_RATE.invert(), Some(p.DMA1), p.GPIOA, p.RCC);
serial.listen(Event::Rxne);
} }
// IDLE LOOP // IDLE LOOP
...@@ -43,7 +47,7 @@ fn idle() -> ! { ...@@ -43,7 +47,7 @@ fn idle() -> ! {
// TASKS // TASKS
// Send back the received byte // Send back the received byte
fn loopback(_t: &mut Threshold, r: USART1_EXTI25::Resources) { fn loopback(_t: &mut Threshold, r: USART1_EXTI25::Resources) {
let serial = Serial(&r.USART1); let serial = Serial(&**r.USART1);
let byte = serial.read().unwrap(); let byte = serial.read().unwrap();
serial.write(byte).unwrap(); serial.write(byte).unwrap();
......
//! Direct Memory Access (DMA)
use core::cell::{Cell, UnsafeCell};
use core::marker::PhantomData;
use core::ops;
use nb;
use stm32f30x::DMA1;
/// DMA error
#[derive(Debug)]
pub enum Error {
/// DMA channel in use
InUse,
/// Previous data got overwritten before it could be read because it was
/// not accessed in a timely fashion
Overrun,
/// Transfer error
Transfer,
}
/// Channel 2 of DMA1
pub struct Dma1Channel2 {
_0: (),
}
/// Channel 4 of DMA1
pub struct Dma1Channel4 {
_0: (),
}
/// Channel 5 of DMA1
pub struct Dma1Channel5 {
_0: (),
}
/// Buffer to be used with a certain DMA `CHANNEL`
// NOTE(packed) workaround for rust-lang/rust#41315
#[repr(packed)]
pub struct Buffer<T, CHANNEL> {
data: UnsafeCell<T>,
flag: Cell<BorrowFlag>,
state: Cell<State>,
_marker: PhantomData<CHANNEL>,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
enum State {
// A new `Buffer` starts in this state. We set it to zero to place this
// buffer in the .bss section
Unlocked = 0,
Locked,
MutLocked,
}
type BorrowFlag = usize;
const UNUSED: BorrowFlag = 0;
const WRITING: BorrowFlag = !0;
/// Wraps a borrowed reference to a value in a `Buffer`
pub struct Ref<'a, T>
where
T: 'a,
{
data: &'a T,
flag: &'a Cell<BorrowFlag>,
}
impl<'a, T> ops::Deref for Ref<'a, T> {
type Target = T;
fn deref(&self) -> &T {
self.data
}
}
impl<'a, T> Drop for Ref<'a, T> {
fn drop(&mut self) {
self.flag.set(self.flag.get() - 1);
}
}
/// A wrapper type for a mutably borrowed value from a `Buffer``
pub struct RefMut<'a, T>
where
T: 'a,
{
data: &'a mut T,
flag: &'a Cell<BorrowFlag>,
}
impl<'a, T> ops::Deref for RefMut<'a, T> {
type Target = T;
fn deref(&self) -> &T {
self.data
}
}
impl<'a, T> ops::DerefMut for RefMut<'a, T> {
fn deref_mut(&mut self) -> &mut T {
self.data
}
}
impl<'a, T> Drop for RefMut<'a, T> {
fn drop(&mut self) {
self.flag.set(UNUSED);
}
}
impl<T, CHANNEL> Buffer<T, CHANNEL> {
/// Creates a new buffer
pub const fn new(data: T) -> Self {
Buffer {
_marker: PhantomData,
data: UnsafeCell::new(data),
flag: Cell::new(0),
state: Cell::new(State::Unlocked),
}
}
/// Immutably borrows the wrapped value.
///
/// The borrow lasts until the returned `Ref` exits scope. Multiple
/// immutable borrows can be taken out at the same time.
///
/// # Panics
///
/// Panics if the value is currently mutably borrowed.
pub fn borrow(&self) -> Ref<T> {
assert_ne!(self.flag.get(), WRITING);
self.flag.set(self.flag.get() + 1);
Ref {
data: unsafe { &*self.data.get() },
flag: &self.flag,
}
}
/// Mutably borrows the wrapped value.
///
/// The borrow lasts until the returned `RefMut` exits scope. The value
/// cannot be borrowed while this borrow is active.
///
/// # Panics
///
/// Panics if the value is currently borrowed.
pub fn borrow_mut(&self) -> RefMut<T> {
assert_eq!(self.flag.get(), UNUSED);
self.flag.set(WRITING);
RefMut {
data: unsafe { &mut *self.data.get() },
flag: &self.flag,
}
}
pub(crate) fn lock(&self) -> &T {
assert_eq!(self.state.get(), State::Unlocked);
assert_ne!(self.flag.get(), WRITING);
self.flag.set(self.flag.get() + 1);
self.state.set(State::Locked);
unsafe { &*self.data.get() }
}
pub(crate) fn lock_mut(&self) -> &mut T {
assert_eq!(self.state.get(), State::Unlocked);
assert_eq!(self.flag.get(), UNUSED);
self.flag.set(WRITING);
self.state.set(State::MutLocked);
unsafe { &mut *self.data.get() }
}
unsafe fn unlock(&self, state: State) {
match state {
State::Locked => self.flag.set(self.flag.get() - 1),
State::MutLocked => self.flag.set(UNUSED),
_ => { /* unreachable!() */ }
}
self.state.set(State::Unlocked);
}
}
// FIXME these `release` methods probably want some of sort of barrier
impl<T> Buffer<T, Dma1Channel2> {
/// Waits until the DMA releases this buffer
pub fn release(&self, dma1: &DMA1) -> nb::Result<(), Error> {
let state = self.state.get();
if state == State::Unlocked {
return Ok(());
}
if dma1.isr.read().teif2().bit_is_set() {
Err(nb::Error::Other(Error::Transfer))
} else if dma1.isr.read().tcif2().bit_is_set() {
unsafe { self.unlock(state) }
dma1.ifcr.write(|w| w.ctcif2().set_bit());
dma1.ccr2.modify(|_, w| w.en().clear_bit());
Ok(())
} else {
Err(nb::Error::WouldBlock)
}
}
}
impl<T> Buffer<T, Dma1Channel4> {
/// Waits until the DMA releases this buffer
pub fn release(&self, dma1: &DMA1) -> nb::Result<(), Error> {
let state = self.state.get();
if state == State::Unlocked {
return Ok(());
}
if dma1.isr.read().teif4().bit_is_set() {
Err(nb::Error::Other(Error::Transfer))
} else if dma1.isr.read().tcif4().bit_is_set() {
unsafe { self.unlock(state) }
dma1.ifcr.write(|w| w.ctcif4().set_bit());
dma1.ccr4.modify(|_, w| w.en().clear_bit());
Ok(())
} else {
Err(nb::Error::WouldBlock)
}
}
}
impl<T> Buffer<T, Dma1Channel5> {
/// Waits until the DMA releases this buffer
pub fn release(&self, dma1: &DMA1) -> nb::Result<(), Error> {
let state = self.state.get();
if state == State::Unlocked {
return Ok(());
}
if dma1.isr.read().teif5().bit_is_set() {
Err(nb::Error::Other(Error::Transfer))
} else if dma1.isr.read().tcif5().bit_is_set() {
unsafe { self.unlock(state) }
dma1.ifcr.write(|w| w.ctcif5().set_bit());
dma1.ccr5.modify(|_, w| w.en().clear_bit());
Ok(())
} else {
Err(nb::Error::WouldBlock)
}
}
}
// pub const AHB: u32 = 8_000_000; //! Definition of bus frequency details for f3.
pub const APB1: u32 = 8_000_000;
pub const APB2: u32 = 8_000_000; macro_rules! frequency {
($FREQUENCY:expr) => {
use time::*;
/// Frequency
pub const FREQUENCY: u32 = $FREQUENCY;
/// Unit of time
#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
pub struct Ticks(pub u32);
impl Ticks {
/// Applies the function `f` to the inner value
pub fn map<F>(self, f: F) -> Self
where F: FnOnce(u32) -> u32,
{
Ticks(f(self.0))
}
}
impl From<Ticks> for Microseconds {
fn from(ticks: Ticks) -> Self {
Microseconds(ticks.0 / (FREQUENCY / 1_000_000))
}
}
impl From<Ticks> for Milliseconds {
fn from(ticks: Ticks) -> Self {
Milliseconds(ticks.0 / (FREQUENCY / 1_000))
}
}
impl From<Ticks> for Seconds {
fn from(ticks: Ticks) -> Self {
Seconds(ticks.0 / FREQUENCY)
}
}
impl From<IHertz> for Ticks {
fn from(ihz: IHertz) -> Ticks {
Ticks(FREQUENCY / ihz.0)
}
}
impl From<Microseconds> for Ticks {
fn from(us: Microseconds) -> Ticks {
Ticks(us.0 * (FREQUENCY / 1_000_000))
}
}
impl From<Milliseconds> for Ticks {
fn from(ms: Milliseconds) -> Ticks {
Ticks(ms.0 * (FREQUENCY / 1_000))
}
}
impl From<Seconds> for Ticks {
fn from(s: Seconds) -> Ticks {
Ticks(s.0 * FREQUENCY)
}
}
impl Into<u32> for Ticks {
fn into(self) -> u32 {
self.0
}
}
}
}
/// Advance High-performance Bus (AHB)
pub mod ahb {
frequency!(8_000_000);
}
/// Advance Peripheral Bus 1 (APB1)
pub mod apb1 {
frequency!(8_000_000);
}
/// Advance Peripheral Bus 2 (APB2)
pub mod apb2 {
frequency!(8_000_000);
}
...@@ -17,16 +17,31 @@ ...@@ -17,16 +17,31 @@
#![deny(missing_docs)] #![deny(missing_docs)]
#![deny(warnings)] #![deny(warnings)]
#![feature(const_fn)]
#![feature(get_type_id)]
#![feature(never_type)]
#![feature(unsize)]
#![no_std] #![no_std]
extern crate cast; extern crate cast;
extern crate embedded_hal as hal;
extern crate nb;
extern crate static_ref;
pub extern crate stm32f30x; pub extern crate stm32f30x;
// For documentation only // For documentation only
pub mod examples; pub mod examples;
pub mod dma;
pub mod led; pub mod led;
pub mod serial; pub mod serial;
pub mod timer; pub mod timer;
pub mod time;
pub mod frequency;
use frequency::*;
pub use hal::prelude;
pub use serial::Serial;
mod frequency;
//! Serial interface //! Serial interface
//! //!
//! - TX - PA9 //! You can use the `Serial` interface with these USART instances
//! - RX - PA10 //!
//! # USART1
//!
//! - TX = PA9
//! - RX = PA10
//! - Interrupt = USART1
use core::any::{Any, TypeId};
use core::marker::Unsize;
use core::ops::Deref;
use core::ptr; use core::ptr;
use cast::{u16, u8}; use cast::u16;
use stm32f30x::{USART1, GPIOA, RCC}; use hal;
use nb;
use static_ref::Static;
use stm32f30x::{gpioa, DMA1, USART1, usart1, GPIOA,
RCC};
use frequency; use dma::{self, Buffer, Dma1Channel4, Dma1Channel5};
/// Specialized `Result` type /// Specialized `Result` type
pub type Result<T> = ::core::result::Result<T, Error>; pub type Result<T> = ::core::result::Result<T, nb::Error<Error>>;
/// IMPLEMENTATION DETAIL
pub unsafe trait Usart: Deref<Target = usart1::RegisterBlock> {
/// IMPLEMENTATION DETAIL
type GPIO: Deref<Target = gpioa::RegisterBlock>;
/// IMPLEMENTATION DETAIL
type Ticks: Into<u32>;
}
unsafe impl Usart for USART1 {
type GPIO = GPIOA;
type Ticks = ::apb2::Ticks;
}
/// An error /// An error
#[derive(Debug)] #[derive(Debug)]
pub enum Error { pub enum Error {
/// De-synchronization, excessive noise or a break character detected
Framing,
/// Noise detected in the received frame
Noise,
/// RX buffer overrun
Overrun,
#[doc(hidden)] #[doc(hidden)]
_Extensible, _Extensible,
} }
/// Interrupt event
pub enum Event {
/// RX buffer Not Empty (new data available)
Rxne,
/// Transmission Complete
Tc,
/// TX buffer Empty (more data can be send)
Txe,
}
/// Serial interface /// Serial interface
/// ///
/// # Interrupts /// # Interrupts
/// ///
/// - `Usart1Exti25` - RXNE (RX buffer not empty) /// - RXNE
pub struct Serial<'a>(pub &'a USART1); pub struct Serial<'a, U>(pub &'a U)
where
U: Any + Usart;
impl<'a, U> Clone for Serial<'a, U>
where
U: Any + Usart,
{
fn clone(&self) -> Self {
*self
}
}
impl<'a, U> Copy for Serial<'a, U>
where
U: Any + Usart,
{
}
impl<'a> Serial<'a> { impl<'a, U> Serial<'a, U>
where
U: Any + Usart,
{
/// Initializes the serial interface with a baud rate of `baut_rate` bits /// Initializes the serial interface with a baud rate of `baut_rate` bits
/// per second /// per second
pub fn init(&self, gpioa: &GPIOA, rcc: &RCC, baud_rate: u32) { ///
let usart1 = self.0; /// The serial interface will be configured to use 8 bits of data, 1 stop
/// bit, no hardware control and to omit parity checking
pub fn init<B>(
&self,
baud_rate: B,
dma1: Option<&DMA1>,
gpio: &U::GPIO,
rcc: &RCC,
) where
B: Into<U::Ticks>,
{
self._init(baud_rate.into(), dma1, gpio, rcc)
}
fn _init(
&self,
baud_rate: U::Ticks,
dma1: Option<&DMA1>,
gpio: &U::GPIO,
rcc: &RCC,
) {
let usart = self.0;
// power up peripherals
if dma1.is_some() {
rcc.ahbenr.modify(|_, w| w.dmaen().enabled());
}
if usart.get_type_id() == TypeId::of::<USART1>() {
rcc.apb2enr.modify(|_, w| {
w.usart1en().enabled()
});
}
rcc.ahbenr.modify(|_, w| w.iopaen().set_bit());
if usart.get_type_id() == TypeId::of::<USART1>() {
// PA9. = TX, PA10 = RX
gpio.afrh.modify(|_, w| {
unsafe {
w.afrh9().bits(7).afrh10().bits(7)
}
});
gpio.moder.modify(|_, w| {
w.moder9().alternate()
.moder10().alternate()
});
}
if let Some(dma1) = dma1 {
if usart.get_type_id() == TypeId::of::<USART1>() {
// TX DMA transfer
// mem2mem: Memory to memory mode disabled
// pl: Medium priority
// msize: Memory size = 8 bits
// psize: Peripheral size = 8 bits
// minc: Memory increment mode enabled
// pinc: Peripheral increment mode disabled
// circ: Circular mode disabled
// dir: Transfer from memory to peripheral
// tceie: Transfer complete interrupt enabled
// en: Disabled
dma1.ccr4.write(|w| unsafe {
w.mem2mem()
.clear_bit()
.pl()
.bits(0b01)
.msize()
.bits(0b00)
.psize()
.bits(0b00)
.minc()
.set_bit()
.circ()
.clear_bit()
.pinc()
.clear_bit()
.dir()
.set_bit()
.tcie()
.set_bit()
.en()
.clear_bit()
});
// RX DMA transfer
// mem2mem: Memory to memory mode disabled
// pl: Medium priority
// msize: Memory size = 8 bits
// psize: Peripheral size = 8 bits
// minc: Memory increment mode enabled
// pinc: Peripheral increment mode disabled
// circ: Circular mode disabled
// dir: Transfer from peripheral to memory
// tceie: Transfer complete interrupt enabled
// en: Disabled
dma1.ccr5.write(|w| unsafe {
w.mem2mem()
.clear_bit()
.pl()
.bits(0b01)
.msize()
.bits(0b00)
.psize()
.bits(0b00)
.minc()
.set_bit()
.circ()
.clear_bit()
.pinc()
.clear_bit()
.dir()
.clear_bit()
.tcie()
.set_bit()
.en()
.clear_bit()
});
}
}
// 8N1
usart.cr2.write(|w| unsafe { w.stop().bits(0b00) });
// baud rate
let brr = baud_rate.into();
assert!(brr >= 16, "impossible baud rate");
usart.brr.write(|w| unsafe { w.bits(brr) });
// Power up the peripherals // disable hardware flow control
rcc.apb2enr.modify(|_, w| w.usart1en().enabled()); // enable DMA TX and RX transfers
rcc.ahbenr.modify(|_, w| w.iopaen().enabled()); usart.cr3.write(|w| {
w.rtse()
// Configure PA9 as TX and PA10 as RX .clear_bit()
gpioa .ctse()
.afrh .clear_bit()
.modify(|_, w| unsafe { w.afrh9().bits(7).afrh10().bits(7) }); .dmat()
gpioa .set_bit()
.moder .dmar()
.modify(|_, w| w.moder9().alternate().moder10().alternate()); .set_bit()
// 8 data bits, 0 stop bits
usart1.cr2.write(|w| unsafe { w.stop().bits(0b00) });
// Disable hardware flow control
usart1
.cr3
.write(|w| w.rtse().clear_bit().ctse().clear_bit());
// set baud rate
let brr = u16(frequency::APB2 / baud_rate).unwrap();
let fraction = u8(brr & 0b1111).unwrap();
let mantissa = brr >> 4;
usart1.brr.write(|w| unsafe {
w.div_fraction()
.bits(fraction)
.div_mantissa()
.bits(mantissa)
}); });
// enable peripheral, transmitter, receiver // enable TX, RX; disable parity checking
// enable RXNE event usart.cr1.write(|w| {
usart1.cr1.write(|w| {
w.ue() w.ue()
.set_bit() .set_bit()
.re() .re()
.set_bit() .set_bit()
.te() .te()
.set_bit() .set_bit()
.pce() .m()
.clear_bit() .clear_bit()
.over8() .over8()
.clear_bit() .clear_bit()
.pce()
.clear_bit()
.rxneie() .rxneie()
.set_bit() .clear_bit()
}); });
} }
/// Reads a byte from the RX buffer /// Starts listening for an interrupt `event`
/// pub fn listen(&self, event: Event) {
/// Returns `None` if the buffer is empty let usart = self.0;
pub fn read(&self) -> Result<u8> {
match event {
Event::Rxne => usart.cr1.modify(|_, w| w.rxneie().set_bit()),
Event::Tc => usart.cr1.modify(|_, w| w.tcie().set_bit()),
Event::Txe => usart.cr1.modify(|_, w| w.txeie().set_bit()),
}
}
/// Stops listening for an interrupt `event`
pub fn unlisten(&self, event: Event) {
let usart = self.0;
match event {
Event::Rxne => usart.cr1.modify(|_, w| w.rxneie().clear_bit()),
Event::Tc => usart.cr1.modify(|_, w| w.tcie().clear_bit()),
Event::Txe => usart.cr1.modify(|_, w| w.txeie().clear_bit()),
}
}
}
impl<'a, U> hal::serial::Read<u8> for Serial<'a, U>
where
U: Any + Usart,
{
type Error = Error;
fn read(&self) -> Result<u8> {
let usart1 = self.0; let usart1 = self.0;
let sr = usart1.isr.read();
if usart1.isr.read().rxne().bit_is_set() { if sr.ore().bit_is_set() {
Err(nb::Error::Other(Error::Overrun))
} else if sr.nf().bit_is_set() {
Err(nb::Error::Other(Error::Noise))
} else if sr.fe().bit_is_set() {
Err(nb::Error::Other(Error::Framing))
} else if sr.rxne().bit_is_set() {
// NOTE(read_volatile) the register is 9 bits big but we'll only // NOTE(read_volatile) the register is 9 bits big but we'll only
// work with the first 8 bits // work with the first 8 bits
Ok(unsafe { Ok(unsafe {
ptr::read_volatile(&usart1.rdr as *const _ as *const u8) ptr::read_volatile(&usart1.rdr as *const _ as *const u8)
}) })
} else { } else {
Err(Error::_Extensible) Err(nb::Error::WouldBlock)
}
} }
} }
/// Writes byte into the TX buffer impl<'a, U> hal::serial::Write<u8> for Serial<'a, U>
/// where
/// Returns `Err` if the buffer is already full U: Any + Usart,
pub fn write(&self, byte: u8) -> Result<()> { {
type Error = Error;
fn write(&self, byte: u8) -> Result<()> {
let usart1 = self.0; let usart1 = self.0;
let sr = usart1.isr.read();
if usart1.isr.read().txe().bit_is_set() { if sr.ore().bit_is_set() {
Err(nb::Error::Other(Error::Overrun))
} else if sr.nf().bit_is_set() {
Err(nb::Error::Other(Error::Noise))
} else if sr.fe().bit_is_set() {
Err(nb::Error::Other(Error::Framing))
} else if sr.txe().bit_is_set() {
// NOTE(write_volatile) see NOTE in the `read` method
unsafe { unsafe {
ptr::write_volatile(&usart1.tdr as *const _ as *mut u8, byte) ptr::write_volatile(&usart1.tdr as *const _ as *mut u8, byte)
} }
Ok(()) Ok(())
} else { } else {
Err(Error::_Extensible) Err(nb::Error::WouldBlock)
}
}
}
impl<'a> Serial<'a, USART1> {
/// Starts a DMA transfer to receive serial data into a `buffer`
///
/// This will mutably lock the `buffer` preventing borrowing its contents
/// The `buffer` can be `release`d after the DMA transfer finishes
// TODO support circular mode + half transfer interrupt as a double
// buffering mode
pub fn read_exact<B>(
&self,
dma1: &DMA1,
buffer: &Static<Buffer<B, Dma1Channel5>>,
) -> ::core::result::Result<(), dma::Error>
where
B: Unsize<[u8]>,
{
let usart1 = self.0;
if dma1.ccr5.read().en().bit_is_set() {
return Err(dma::Error::InUse);
} }
let buffer: &mut [u8] = buffer.lock_mut();
dma1.cndtr5
.write(|w| unsafe { w.ndt().bits(u16(buffer.len()).unwrap()) });
dma1.cpar5
.write(|w| unsafe { w.bits(&usart1.rdr as *const _ as u32) });
dma1.cmar5
.write(|w| unsafe { w.bits(buffer.as_ptr() as u32) });
dma1.ccr5.modify(|_, w| w.en().set_bit());
Ok(())
}
/// Starts a DMA transfer to send `buffer` through this serial port
///
/// This will immutably lock the `buffer` preventing mutably borrowing its
/// contents. The `buffer` can be `release`d after the DMA transfer finishes
pub fn write_all<B>(
&self,
dma1: &DMA1,
buffer: &Static<Buffer<B, Dma1Channel4>>,
) -> ::core::result::Result<(), dma::Error>
where
B: Unsize<[u8]>,
{
let usart1 = self.0;
if dma1.ccr4.read().en().bit_is_set() {
return Err(dma::Error::InUse);
}
let buffer: &[u8] = buffer.lock();
dma1.cndtr4
.write(|w| unsafe { w.ndt().bits(u16(buffer.len()).unwrap()) });
dma1.cpar4
.write(|w| unsafe { w.bits(&usart1.tdr as *const _ as u32) });
dma1.cmar4
.write(|w| unsafe { w.bits(buffer.as_ptr() as u32) });
dma1.ccr4.modify(|_, w| w.en().set_bit());
Ok(())
} }
} }
//! Units of time
macro_rules! map {
($Self:ident) => {
impl $Self {
/// Applies the function `f` to inner value
pub fn map<F>(self, f: F) -> $Self
where
F: FnOnce(u32) -> u32
{
$Self(f(self.0))
}
}
}
}
/// `Hz^-1`
#[derive(Clone, Copy, Debug)]
pub struct IHertz(pub u32);
impl IHertz {
/// Invert this quantity
pub fn invert(self) -> Hertz {
Hertz(self.0)
}
}
map!(IHertz);
/// `Hz`
#[derive(Clone, Copy, Debug)]
pub struct Hertz(pub u32);
impl Hertz {
/// Invert this quantity
pub fn invert(self) -> IHertz {
IHertz(self.0)
}
}
map!(Hertz);
/// `us`
#[derive(Clone, Copy, Debug)]
pub struct Microseconds(pub u32);
map!(Microseconds);
/// `ms`
#[derive(Clone, Copy, Debug)]
pub struct Milliseconds(pub u32);
map!(Milliseconds);
/// `s`
#[derive(Clone, Copy, Debug)]
pub struct Seconds(pub u32);
map!(Seconds);
/// `u32` extension trait
pub trait U32Ext {
/// Wrap in `Hz`
fn hz(self) -> Hertz;
/// Wrap in `Milliseconds`
fn ms(self) -> Milliseconds;
/// Wrap in `Seconds`
fn s(self) -> Seconds;
/// Wrap in `Microseconds`
fn us(self) -> Microseconds;
}
impl U32Ext for u32 {
fn hz(self) -> Hertz {
Hertz(self)
}
fn ms(self) -> Milliseconds {
Milliseconds(self)
}
fn s(self) -> Seconds {
Seconds(self)
}
fn us(self) -> Microseconds {
Microseconds(self)
}
}
...@@ -5,8 +5,6 @@ use core::u16; ...@@ -5,8 +5,6 @@ use core::u16;
use cast::{u16, u32}; use cast::{u16, u32};
use stm32f30x::{RCC, TIM7}; use stm32f30x::{RCC, TIM7};
use frequency;
/// Specialized `Result` type /// Specialized `Result` type
pub type Result<T> = ::core::result::Result<T, Error>; pub type Result<T> = ::core::result::Result<T, Error>;
...@@ -32,7 +30,7 @@ impl<'a> Timer<'a> { ...@@ -32,7 +30,7 @@ impl<'a> Timer<'a> {
// Power up peripherals // Power up peripherals
rcc.apb1enr.modify(|_, w| w.tim7en().enabled()); rcc.apb1enr.modify(|_, w| w.tim7en().enabled());
let ratio = frequency::APB1 / frequency; let ratio = ::apb1::FREQUENCY / frequency;
let psc = u16((ratio - 1) / u32(u16::MAX)).unwrap(); let psc = u16((ratio - 1) / u32(u16::MAX)).unwrap();
tim7.psc.write(|w| w.psc().bits(psc)); tim7.psc.write(|w| w.psc().bits(psc));
let arr = u16(ratio / u32(psc + 1)).unwrap(); let arr = u16(ratio / u32(psc + 1)).unwrap();
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment