diff --git a/CHANGELOG.md b/CHANGELOG.md index b15609c3..c43c4a8c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,11 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Fixed -- Fix period retrival for timers +- Fix period retrieval for timers + +### Changed + +- Use `Deref` for I2C generic implementations instead of macros ## [v0.6.0] - 2020-06-06 diff --git a/src/i2c.rs b/src/i2c.rs index 11f82d95..cf1d77f2 100644 --- a/src/i2c.rs +++ b/src/i2c.rs @@ -9,8 +9,9 @@ use crate::gpio::gpiob::{PB10, PB11, PB6, PB7, PB8, PB9}; use crate::gpio::{Alternate, OpenDrain}; use crate::hal::blocking::i2c::{Read, Write, WriteRead}; use crate::pac::{DWT, I2C1, I2C2}; -use crate::rcc::{sealed::RccBus, Clocks, Enable, GetBusFreq, Reset, APB1}; +use crate::rcc::{Clocks, Enable, GetBusFreq, Reset, APB1}; use crate::time::Hertz; +use core::ops::Deref; use nb::Error::{Other, WouldBlock}; use nb::{Error as NbError, Result as NbResult}; @@ -119,7 +120,7 @@ impl I2c { PINS: Pins, { mapr.modify_mapr(|_, w| w.i2c1_remap().bit(PINS::REMAP)); - I2c::_i2c1(i2c, pins, mode, clocks, apb) + I2c::::_i2c(i2c, pins, mode, clocks, apb) } } @@ -141,7 +142,7 @@ impl BlockingI2c { PINS: Pins, { mapr.modify_mapr(|_, w| w.i2c1_remap().bit(PINS::REMAP)); - BlockingI2c::_i2c1( + BlockingI2c::::_i2c( i2c, pins, mode, @@ -161,7 +162,7 @@ impl I2c { where PINS: Pins, { - I2c::_i2c2(i2c, pins, mode, clocks, apb) + I2c::::_i2c(i2c, pins, mode, clocks, apb) } } @@ -181,7 +182,7 @@ impl BlockingI2c { where PINS: Pins, { - BlockingI2c::_i2c2( + BlockingI2c::::_i2c( i2c, pins, mode, @@ -259,279 +260,305 @@ macro_rules! busy_wait_cycles { }}; } -// Generate the same code for both I2Cs -macro_rules! hal { - ($($I2CX:ident: ($i2cX:ident),)+) => { - $( - impl I2c<$I2CX, PINS> { - /// Configures the I2C peripheral to work in master mode - fn $i2cX( - i2c: $I2CX, - pins: PINS, - mode: Mode, - clocks: Clocks, - apb: &mut <$I2CX as RccBus>::Bus, - ) -> Self { - $I2CX::enable(apb); - $I2CX::reset(apb); - - let pclk1 = <$I2CX as RccBus>::Bus::get_frequency(&clocks).0; - - assert!(mode.get_frequency().0 <= 400_000); - - let mut i2c = I2c { i2c, pins, mode, pclk1 }; - i2c.init(); - i2c - } +pub type I2cRegisterBlock = crate::pac::i2c1::RegisterBlock; - /// Initializes I2C. Configures the `I2C_TRISE`, `I2C_CRX`, and `I2C_CCR` registers - /// according to the system frequency and I2C mode. - fn init(&mut self) { - let freq = self.mode.get_frequency(); - let pclk1_mhz = (self.pclk1 / 1000000) as u16; - - self.i2c.cr2.write(|w| unsafe { - w.freq().bits(pclk1_mhz as u8) - }); - self.i2c.cr1.write(|w| w.pe().clear_bit()); - - match self.mode { - Mode::Standard { .. } => { - self.i2c.trise.write(|w| { - w.trise().bits((pclk1_mhz + 1) as u8) - }); - self.i2c.ccr.write(|w| unsafe { - w.ccr().bits(((self.pclk1 / (freq.0 * 2)) as u16).max(4)) - }); - }, - Mode::Fast { ref duty_cycle, .. } => { - self.i2c.trise.write(|w| { - w.trise().bits((pclk1_mhz * 300 / 1000 + 1) as u8) - }); - - self.i2c.ccr.write(|w| { - let (freq, duty) = match duty_cycle { - DutyCycle::Ratio2to1 => (((self.pclk1 / (freq.0* 3)) as u16).max(1), false), - DutyCycle::Ratio16to9 => (((self.pclk1 / (freq.0 * 25)) as u16).max(1), true) - }; - - unsafe { - w.ccr().bits(freq).duty().bit(duty).f_s().set_bit() - } - }); - } - }; +impl I2c +where + I2C: Deref + Enable + Reset, + I2C::Bus: GetBusFreq, +{ + /// Configures the I2C peripheral to work in master mode + fn _i2c(i2c: I2C, pins: PINS, mode: Mode, clocks: Clocks, apb: &mut I2C::Bus) -> Self { + I2C::enable(apb); + I2C::reset(apb); - self.i2c.cr1.modify(|_, w| w.pe().set_bit()); - } + let pclk1 = I2C::Bus::get_frequency(&clocks).0; - /// Perform an I2C software reset - fn reset(&mut self) { - self.i2c.cr1.write(|w| w.pe().set_bit().swrst().set_bit()); - self.i2c.cr1.reset(); - self.init(); - } + assert!(mode.get_frequency().0 <= 400_000); - /// Generate START condition - fn send_start(&mut self) { - self.i2c.cr1.modify(|_, w| w.start().set_bit()); - } + let mut i2c = I2c { + i2c, + pins, + mode, + pclk1, + }; + i2c.init(); + i2c + } +} - /// Check if START condition is generated. If the condition is not generated, this - /// method returns `WouldBlock` so the program can act accordingly - /// (busy wait, async, ...) - fn wait_after_sent_start(&mut self) -> NbResult<(), Error> { - wait_for_flag!(self.i2c, sb) - } +impl I2c +where + I2C: Deref, +{ + /// Initializes I2C. Configures the `I2C_TRISE`, `I2C_CRX`, and `I2C_CCR` registers + /// according to the system frequency and I2C mode. + fn init(&mut self) { + let freq = self.mode.get_frequency(); + let pclk1_mhz = (self.pclk1 / 1000000) as u16; + + self.i2c + .cr2 + .write(|w| unsafe { w.freq().bits(pclk1_mhz as u8) }); + self.i2c.cr1.write(|w| w.pe().clear_bit()); + + match self.mode { + Mode::Standard { .. } => { + self.i2c + .trise + .write(|w| w.trise().bits((pclk1_mhz + 1) as u8)); + self.i2c.ccr.write(|w| unsafe { + w.ccr().bits(((self.pclk1 / (freq.0 * 2)) as u16).max(4)) + }); + } + Mode::Fast { ref duty_cycle, .. } => { + self.i2c + .trise + .write(|w| w.trise().bits((pclk1_mhz * 300 / 1000 + 1) as u8)); + + self.i2c.ccr.write(|w| { + let (freq, duty) = match duty_cycle { + &DutyCycle::Ratio2to1 => { + (((self.pclk1 / (freq.0 * 3)) as u16).max(1), false) + } + &DutyCycle::Ratio16to9 => { + (((self.pclk1 / (freq.0 * 25)) as u16).max(1), true) + } + }; - /// Check if STOP condition is generated. If the condition is not generated, this - /// method returns `WouldBlock` so the program can act accordingly - /// (busy wait, async, ...) - fn wait_for_stop(&mut self) -> NbResult<(), Error> { - if self.i2c.cr1.read().stop().is_no_stop() { - Ok(()) - } else { - Err(WouldBlock) - } - } + unsafe { w.ccr().bits(freq).duty().bit(duty).f_s().set_bit() } + }); + } + }; - /// Sends the (7-Bit) address on the I2C bus. The 8th bit on the bus is set - /// depending on wether it is a read or write transfer. - fn send_addr(&self, addr: u8, read: bool) { - self.i2c.dr.write(|w| { w.dr().bits(addr << 1 | (if read {1} else {0})) }); - } + self.i2c.cr1.modify(|_, w| w.pe().set_bit()); + } - /// Generate STOP condition - fn send_stop(&self) { - self.i2c.cr1.modify(|_, w| w.stop().set_bit()); - } + /// Perform an I2C software reset + fn reset(&mut self) { + self.i2c.cr1.write(|w| w.pe().set_bit().swrst().set_bit()); + self.i2c.cr1.reset(); + self.init(); + } - /// Releases the I2C peripheral and associated pins - pub fn free(self) -> ($I2CX, PINS) { - (self.i2c, self.pins) - } - } + /// Generate START condition + fn send_start(&mut self) { + self.i2c.cr1.modify(|_, w| w.start().set_bit()); + } - impl BlockingI2c<$I2CX, PINS> { - fn $i2cX( - i2c: $I2CX, - pins: PINS, - mode: Mode, - clocks: Clocks, - apb: &mut <$I2CX as RccBus>::Bus, - start_timeout_us: u32, - start_retries: u8, - addr_timeout_us: u32, - data_timeout_us: u32 - ) -> Self { - blocking_i2c(I2c::$i2cX(i2c, pins, mode, clocks, apb), - clocks, start_timeout_us, start_retries, - addr_timeout_us, data_timeout_us) - } + /// Check if START condition is generated. If the condition is not generated, this + /// method returns `WouldBlock` so the program can act accordingly + /// (busy wait, async, ...) + fn wait_after_sent_start(&mut self) -> NbResult<(), Error> { + wait_for_flag!(self.i2c, sb) + } - fn send_start_and_wait(&mut self) -> NbResult<(), Error> { - // According to http://www.st.com/content/ccc/resource/technical/document/errata_sheet/f5/50/c9/46/56/db/4a/f6/CD00197763.pdf/files/CD00197763.pdf/jcr:content/translations/en.CD00197763.pdf - // 2.14.4 Wrong behavior of I2C peripheral in master mode after a misplaced STOP - let mut retries_left = self.start_retries; - let mut last_ret: NbResult<(), Error> = Err(WouldBlock); - while retries_left > 0 { - self.nb.send_start(); - last_ret = busy_wait_cycles!(self.nb.wait_after_sent_start(), self.start_timeout); - if last_ret.is_err() { - self.nb.reset(); - } else { - break; - } - retries_left -= 1; - } - last_ret - } + /// Check if STOP condition is generated. If the condition is not generated, this + /// method returns `WouldBlock` so the program can act accordingly + /// (busy wait, async, ...) + fn wait_for_stop(&mut self) -> NbResult<(), Error> { + if self.i2c.cr1.read().stop().is_no_stop() { + Ok(()) + } else { + Err(WouldBlock) + } + } - fn write_without_stop(&mut self, addr: u8, bytes: &[u8]) -> NbResult<(), Error> { - self.send_start_and_wait()?; - self.nb.i2c.sr1.read(); - self.nb.send_addr(addr, false); + /// Sends the (7-Bit) address on the I2C bus. The 8th bit on the bus is set + /// depending on wether it is a read or write transfer. + fn send_addr(&self, addr: u8, read: bool) { + self.i2c + .dr + .write(|w| w.dr().bits(addr << 1 | (if read { 1 } else { 0 }))); + } - busy_wait_cycles!(wait_for_flag!(self.nb.i2c, addr), self.addr_timeout)?; - self.nb.i2c.sr1.read(); - self.nb.i2c.sr2.read(); + /// Generate STOP condition + fn send_stop(&self) { + self.i2c.cr1.modify(|_, w| w.stop().set_bit()); + } - self.nb.i2c.dr.write(|w| { w.dr().bits(bytes[0]) }); + /// Releases the I2C peripheral and associated pins + pub fn free(self) -> (I2C, PINS) { + (self.i2c, self.pins) + } +} - for byte in &bytes[1..] { - busy_wait_cycles!(wait_for_flag!(self.nb.i2c, tx_e), self.data_timeout)?; - self.nb.i2c.dr.write(|w| { w.dr().bits(*byte) }); - } - busy_wait_cycles!(wait_for_flag!(self.nb.i2c, btf), self.data_timeout)?; +impl BlockingI2c +where + I2C: Deref + Enable + Reset, + I2C::Bus: GetBusFreq, +{ + fn _i2c( + i2c: I2C, + pins: PINS, + mode: Mode, + clocks: Clocks, + apb: &mut I2C::Bus, + start_timeout_us: u32, + start_retries: u8, + addr_timeout_us: u32, + data_timeout_us: u32, + ) -> Self { + blocking_i2c( + I2c::::_i2c(i2c, pins, mode, clocks, apb), + clocks, + start_timeout_us, + start_retries, + addr_timeout_us, + data_timeout_us, + ) + } +} - Ok(()) - } +impl BlockingI2c +where + I2C: Deref, +{ + fn send_start_and_wait(&mut self) -> NbResult<(), Error> { + // According to http://www.st.com/content/ccc/resource/technical/document/errata_sheet/f5/50/c9/46/56/db/4a/f6/CD00197763.pdf/files/CD00197763.pdf/jcr:content/translations/en.CD00197763.pdf + // 2.14.4 Wrong behavior of I2C peripheral in master mode after a misplaced STOP + let mut retries_left = self.start_retries; + let mut last_ret: NbResult<(), Error> = Err(WouldBlock); + while retries_left > 0 { + self.nb.send_start(); + last_ret = busy_wait_cycles!(self.nb.wait_after_sent_start(), self.start_timeout); + if let Err(_) = last_ret { + self.nb.reset(); + } else { + break; } + retries_left -= 1; + } + last_ret + } - impl Write for BlockingI2c<$I2CX, PINS> { - type Error = NbError; + fn write_without_stop(&mut self, addr: u8, bytes: &[u8]) -> NbResult<(), Error> { + self.send_start_and_wait()?; + self.nb.i2c.sr1.read(); + self.nb.send_addr(addr, false); - fn write(&mut self, addr: u8, bytes: &[u8]) -> Result<(), Self::Error> { - self.write_without_stop(addr, bytes)?; - self.nb.send_stop(); - busy_wait_cycles!(self.nb.wait_for_stop(), self.data_timeout)?; + busy_wait_cycles!(wait_for_flag!(self.nb.i2c, addr), self.addr_timeout)?; + self.nb.i2c.sr1.read(); + self.nb.i2c.sr2.read(); - Ok(()) - } - } + self.nb.i2c.dr.write(|w| w.dr().bits(bytes[0])); - impl Read for BlockingI2c<$I2CX, PINS> { - type Error = NbError; + for byte in &bytes[1..] { + busy_wait_cycles!(wait_for_flag!(self.nb.i2c, tx_e), self.data_timeout)?; + self.nb.i2c.dr.write(|w| w.dr().bits(*byte)); + } + busy_wait_cycles!(wait_for_flag!(self.nb.i2c, btf), self.data_timeout)?; - fn read(&mut self, addr: u8, buffer: &mut [u8]) -> Result<(), Self::Error> { - self.send_start_and_wait()?; - self.nb.i2c.sr1.read(); - self.nb.send_addr(addr, true); - busy_wait_cycles!(wait_for_flag!(self.nb.i2c, addr), self.addr_timeout)?; + Ok(()) + } +} - match buffer.len() { - 1 => { - self.nb.i2c.cr1.modify(|_, w| w.ack().clear_bit()); - self.nb.i2c.sr1.read(); - self.nb.i2c.sr2.read(); - self.nb.send_stop(); +impl Write for BlockingI2c +where + I2C: Deref, +{ + type Error = NbError; - busy_wait_cycles!(wait_for_flag!(self.nb.i2c, rx_ne), self.data_timeout)?; - buffer[0] = self.nb.i2c.dr.read().dr().bits(); + fn write(&mut self, addr: u8, bytes: &[u8]) -> Result<(), Self::Error> { + self.write_without_stop(addr, bytes)?; + self.nb.send_stop(); + busy_wait_cycles!(self.nb.wait_for_stop(), self.data_timeout)?; - busy_wait_cycles!(self.nb.wait_for_stop(), self.data_timeout)?; - self.nb.i2c.cr1.modify(|_, w| w.ack().set_bit()); - } - 2 => { - self.nb.i2c.cr1.modify(|_, w| w.pos().set_bit().ack().set_bit()); - self.nb.i2c.sr1.read(); - self.nb.i2c.sr2.read(); - self.nb.i2c.cr1.modify(|_, w| w.ack().clear_bit()); - - busy_wait_cycles!(wait_for_flag!(self.nb.i2c, btf), self.data_timeout)?; - self.nb.send_stop(); - buffer[0] = self.nb.i2c.dr.read().dr().bits(); - buffer[1] = self.nb.i2c.dr.read().dr().bits(); - - busy_wait_cycles!(self.nb.wait_for_stop(), self.data_timeout)?; - self.nb.i2c.cr1.modify(|_, w| w.pos().clear_bit().ack().clear_bit()); - self.nb.i2c.cr1.modify(|_, w| w.ack().set_bit()); - } - buffer_len => { - self.nb.i2c.sr1.read(); - self.nb.i2c.sr2.read(); - - let (first_bytes, last_two_bytes) = buffer.split_at_mut(buffer_len - 3); - for byte in first_bytes { - busy_wait_cycles!(wait_for_flag!(self.nb.i2c, rx_ne), self.data_timeout)?; - *byte = self.nb.i2c.dr.read().dr().bits(); - } - - busy_wait_cycles!(wait_for_flag!(self.nb.i2c, btf), self.data_timeout)?; - self.nb.i2c.cr1.modify(|_, w| w.ack().clear_bit()); - last_two_bytes[0] = self.nb.i2c.dr.read().dr().bits(); - self.nb.send_stop(); - last_two_bytes[1] = self.nb.i2c.dr.read().dr().bits(); - busy_wait_cycles!(wait_for_flag!(self.nb.i2c, rx_ne), self.data_timeout)?; - last_two_bytes[2] = self.nb.i2c.dr.read().dr().bits(); - - busy_wait_cycles!(self.nb.wait_for_stop(), self.data_timeout)?; - self.nb.i2c.cr1.modify(|_, w| w.ack().set_bit()); - } - } + Ok(()) + } +} - Ok(()) - } +impl Read for BlockingI2c +where + I2C: Deref, +{ + type Error = NbError; + + fn read(&mut self, addr: u8, buffer: &mut [u8]) -> Result<(), Self::Error> { + self.send_start_and_wait()?; + self.nb.i2c.sr1.read(); + self.nb.send_addr(addr, true); + busy_wait_cycles!(wait_for_flag!(self.nb.i2c, addr), self.addr_timeout)?; + + match buffer.len() { + 1 => { + self.nb.i2c.cr1.modify(|_, w| w.ack().clear_bit()); + self.nb.i2c.sr1.read(); + self.nb.i2c.sr2.read(); + self.nb.send_stop(); + + busy_wait_cycles!(wait_for_flag!(self.nb.i2c, rx_ne), self.data_timeout)?; + buffer[0] = self.nb.i2c.dr.read().dr().bits(); + + busy_wait_cycles!(self.nb.wait_for_stop(), self.data_timeout)?; + self.nb.i2c.cr1.modify(|_, w| w.ack().set_bit()); } - - impl WriteRead for BlockingI2c<$I2CX, PINS> { - type Error = NbError; - - fn write_read( - &mut self, - addr: u8, - bytes: &[u8], - buffer: &mut [u8], - ) -> Result<(), Self::Error> { - if !bytes.is_empty() { - self.write_without_stop(addr, bytes)?; - } - - if !buffer.is_empty() { - self.read(addr, buffer)?; - } else if !bytes.is_empty() { - self.nb.send_stop(); - busy_wait_cycles!(self.nb.wait_for_stop(), self.data_timeout)?; - } - - Ok(()) + 2 => { + self.nb + .i2c + .cr1 + .modify(|_, w| w.pos().set_bit().ack().set_bit()); + self.nb.i2c.sr1.read(); + self.nb.i2c.sr2.read(); + self.nb.i2c.cr1.modify(|_, w| w.ack().clear_bit()); + + busy_wait_cycles!(wait_for_flag!(self.nb.i2c, btf), self.data_timeout)?; + self.nb.send_stop(); + buffer[0] = self.nb.i2c.dr.read().dr().bits(); + buffer[1] = self.nb.i2c.dr.read().dr().bits(); + + busy_wait_cycles!(self.nb.wait_for_stop(), self.data_timeout)?; + self.nb + .i2c + .cr1 + .modify(|_, w| w.pos().clear_bit().ack().clear_bit()); + self.nb.i2c.cr1.modify(|_, w| w.ack().set_bit()); + } + buffer_len => { + self.nb.i2c.sr1.read(); + self.nb.i2c.sr2.read(); + + let (first_bytes, last_two_bytes) = buffer.split_at_mut(buffer_len - 3); + for byte in first_bytes { + busy_wait_cycles!(wait_for_flag!(self.nb.i2c, rx_ne), self.data_timeout)?; + *byte = self.nb.i2c.dr.read().dr().bits(); } + + busy_wait_cycles!(wait_for_flag!(self.nb.i2c, btf), self.data_timeout)?; + self.nb.i2c.cr1.modify(|_, w| w.ack().clear_bit()); + last_two_bytes[0] = self.nb.i2c.dr.read().dr().bits(); + self.nb.send_stop(); + last_two_bytes[1] = self.nb.i2c.dr.read().dr().bits(); + busy_wait_cycles!(wait_for_flag!(self.nb.i2c, rx_ne), self.data_timeout)?; + last_two_bytes[2] = self.nb.i2c.dr.read().dr().bits(); + + busy_wait_cycles!(self.nb.wait_for_stop(), self.data_timeout)?; + self.nb.i2c.cr1.modify(|_, w| w.ack().set_bit()); } - )+ + } + + Ok(()) } } -hal! { - I2C1: (_i2c1), - I2C2: (_i2c2), +impl WriteRead for BlockingI2c +where + I2C: Deref, +{ + type Error = NbError; + + fn write_read(&mut self, addr: u8, bytes: &[u8], buffer: &mut [u8]) -> Result<(), Self::Error> { + if !bytes.is_empty() { + self.write_without_stop(addr, bytes)?; + } + + if !buffer.is_empty() { + self.read(addr, buffer)?; + } else if !bytes.is_empty() { + self.nb.send_stop(); + busy_wait_cycles!(self.nb.wait_for_stop(), self.data_timeout)?; + } + + Ok(()) + } } diff --git a/src/spi.rs b/src/spi.rs index 43d7d2e7..7811e2ee 100644 --- a/src/spi.rs +++ b/src/spi.rs @@ -203,7 +203,7 @@ impl Spi { } } -type SpiRegisterBlock = crate::pac::spi1::RegisterBlock; +pub type SpiRegisterBlock = crate::pac::spi1::RegisterBlock; impl Spi where