diff --git a/src/i2c/blocking.rs b/src/i2c/blocking.rs index f337167..ea8d456 100644 --- a/src/i2c/blocking.rs +++ b/src/i2c/blocking.rs @@ -1,11 +1,12 @@ //! I2C -use crate::gpio::*; -use crate::i2c::config::Config; -use crate::i2c::{ - self, Error, I2c, I2cDirection, I2cExt, I2cPeripheral, I2cPeripheralEvent, SCLPin, SDAPin, +use super::config::Config; +use super::{ + Error, I2c, I2cDirection, I2cExt, I2cPeripheral, I2cPeripheralEvent, Instance, SCLPin, SDAPin, }; +use crate::gpio::*; +use crate::i2c; use crate::rcc::*; -use crate::stm32::{I2C1, I2C2}; +use crate::stm32 as pac; pub trait I2cSlave { /// Enable/Disable Slave Byte Control. Default SBC is switched on. @@ -113,7 +114,7 @@ macro_rules! busy_wait { } macro_rules! i2c { - ($I2CX:ident, $i2cx:ident, + ($I2CX:ty, sda: [ $($PSDA:ty,)+ ], scl: [ $($PSCL:ty,)+ ], ) => { @@ -140,423 +141,420 @@ macro_rules! i2c { } } )+ + } +} - impl I2cExt<$I2CX> for $I2CX { - fn i2c( - self, - sda: SDA, - scl: SCL, - config: impl Into, - rcc: &mut Rcc, - ) -> I2c<$I2CX, SDA, SCL> - where - SDA: SDAPin<$I2CX>, - SCL: SCLPin<$I2CX>, - { - I2c::$i2cx(self, sda, scl, config, rcc) - } - } - - impl I2c<$I2CX, SDA, SCL> where - SDA: SDAPin<$I2CX>, - SCL: SCLPin<$I2CX> - { - pub fn $i2cx(i2c: $I2CX, sda: SDA, scl: SCL, config: impl Into, rcc: &mut Rcc) -> Self - where - SDA: SDAPin<$I2CX>, - SCL: SCLPin<$I2CX>, - { - let config = config.into(); - $I2CX::enable(rcc); - $I2CX::reset(rcc); - - // Make sure the I2C unit is disabled so we can configure it - i2c.cr1().modify(|_, w| w.pe().clear_bit()); - - // Setup protocol timings - let timing_bits = config.timing_bits(rcc.clocks.apb_clk); - i2c.timingr().write(|w| unsafe { w.bits(timing_bits) }); - - // Enable the I2C processing - i2c.cr1().modify(|_, w| { - w.pe().set_bit(); - w.dnf().set(config.digital_filter); - w.anfoff().bit(!config.analog_filter) - }); - - if config.slave_address_1 > 0 { - i2c.oar1().write(|w| - unsafe { w.oa1().bits(config.slave_address_1) } - .oa1mode().bit(config.address_11bits) - .oa1en().set_bit() - ); - // Enable acknowlidge control - i2c.cr1().modify(|_, w| w.sbc().set_bit() ); - } +impl I2cExt for I2C { + fn i2c( + self, + sda: SDA, + scl: SCL, + config: impl Into, + rcc: &mut Rcc, + ) -> I2c + where + SDA: SDAPin, + SCL: SCLPin, + { + I2c::new(self, sda, scl, config, rcc) + } +} - if config.slave_address_2 > 0 { - i2c.oar2().write(|w| { - w.oa2msk().set(config.slave_address_mask as u8); - w.oa2().set(config.slave_address_2); - w.oa2en().set_bit() - }); - // Enable acknowlidge control - i2c.cr1().modify(|_, w| w.sbc().set_bit() ); +impl I2c +where + SDA: SDAPin, + SCL: SCLPin, +{ + pub fn new(i2c: I2C, sda: SDA, scl: SCL, config: impl Into, rcc: &mut Rcc) -> Self + where + SDA: SDAPin, + SCL: SCLPin, + { + let config = config.into(); + I2C::enable(rcc); + I2C::reset(rcc); + + // Make sure the I2C unit is disabled so we can configure it + i2c.cr1().modify(|_, w| w.pe().clear_bit()); + + // Setup protocol timings + let timing_bits = config.timing_bits(rcc.clocks.apb_clk); + i2c.timingr().write(|w| unsafe { w.bits(timing_bits) }); + + // Enable the I2C processing + i2c.cr1().modify(|_, w| { + w.pe().set_bit(); + w.dnf().set(config.digital_filter); + w.anfoff().bit(!config.analog_filter) + }); + + if config.slave_address_1 > 0 { + i2c.oar1().write(|w| { + unsafe { + w.oa1().bits(config.slave_address_1); } + w.oa1mode().bit(config.address_11bits); + w.oa1en().set_bit() + }); + // Enable acknowlidge control + i2c.cr1().modify(|_, w| w.sbc().set_bit()); + } - // Enable pins - sda.setup(); - scl.setup(); + if config.slave_address_2 > 0 { + i2c.oar2().write(|w| { + w.oa2msk().set(config.slave_address_mask as u8); + w.oa2().set(config.slave_address_2); + w.oa2en().set_bit() + }); + // Enable acknowlidge control + i2c.cr1().modify(|_, w| w.sbc().set_bit()); + } - I2c { i2c, sda, scl } - } + // Enable pins + sda.setup(); + scl.setup(); - pub fn listen(&mut self, ev: i2c::Event) { - match ev { - i2c::Event::AddressMatch => self.i2c.cr1().modify(|_, w| w.addrie().set_bit()), - i2c::Event::Rxne => self.i2c.cr1().modify(|_, w| w.rxie().set_bit()), - }; - } + I2c { i2c, sda, scl } + } - pub fn unlisten(&mut self, ev: i2c::Event) { - match ev { - i2c::Event::AddressMatch => self.i2c.cr1().modify(|_, w| w.addrie().clear_bit()), - i2c::Event::Rxne => self.i2c.cr1().modify(|_, w| w.rxie().clear_bit()), - }; - } + pub fn listen(&mut self, ev: super::Event) { + match ev { + super::Event::AddressMatch => self.i2c.cr1().modify(|_, w| w.addrie().set_bit()), + super::Event::Rxne => self.i2c.cr1().modify(|_, w| w.rxie().set_bit()), + }; + } - pub fn clear_irq(&mut self, ev: i2c::Event) { - match ev { - i2c::Event::AddressMatch => { - self.i2c.icr().write(|w| w.addrcf().set_bit()); - } - _ => {}, - } - } + pub fn unlisten(&mut self, ev: super::Event) { + match ev { + super::Event::AddressMatch => self.i2c.cr1().modify(|_, w| w.addrie().clear_bit()), + super::Event::Rxne => self.i2c.cr1().modify(|_, w| w.rxie().clear_bit()), + }; + } - pub fn release(self) -> ($I2CX, SDA, SCL) { - (self.i2c, self.sda.release(), self.scl.release()) - } + pub fn clear_irq(&mut self, ev: super::Event) { + if ev == super::Event::AddressMatch { + self.i2c.icr().write(|w| w.addrcf().set_bit()); } + } - impl I2c<$I2CX, SDA, SCL> { - pub fn write_read( - &mut self, - addr: u8, - snd_buffer: &[u8], - rcv_buffer: &mut [u8], - ) -> Result<(), Error> { - // TODO support transfers of more than 255 bytes - let sndlen = snd_buffer.len(); - let rcvlen = rcv_buffer.len(); - assert!(sndlen < 256 && sndlen > 0); - assert!(rcvlen < 256 && rcvlen > 0); - - // Wait for any previous address sequence to end automatically. - // This could be up to 50% of a bus cycle (ie. up to 0.5/freq) - while self.i2c.cr2().read().start().bit_is_set() {}; - - // flush i2c tx register - self.i2c.isr().write(|w| w.txe().set_bit()); - - // Set START and prepare to send `bytes`. - // The START bit can be set even if the bus is BUSY or - // I2C is in slave mode. - self.i2c.cr2().write(|w| { - // Set number of bytes to transfer - w.nbytes().set(sndlen as u8); - // Set address to transfer to/from - w.sadd().set((addr << 1) as u16); - // 7-bit addressing mode - w.add10().clear_bit(); - // Set transfer direction to write - w.rd_wrn().clear_bit(); - // Software end mode - w.autoend().clear_bit(); - w.reload().clear_bit(); - // Start transfer - w.start().set_bit() - }); - let mut idx = 0; - // Wait until we are allowed to send data - // (START has been ACKed or last byte went through) - // macro will return false when the tc bit is set - for byte in snd_buffer { - busy_wait!(self.i2c, txis, bit_is_set, idx, sndlen); - // Put byte on the wire - self.i2c.txdr().write(|w| w.txdata().set(*byte)); - idx += 1; - } - // Wait until the write finishes before beginning to read. - let dummy = 0xFE; - busy_wait!(self.i2c, tc, bit_is_set, idx, dummy ); - - // reSTART and prepare to receive bytes into `rcv_buffer` - self.i2c.cr2().write(|w| { - // Set number of bytes to transfer - w.nbytes().set(rcvlen as u8); - // Set address to transfer to/from - w.sadd().set((addr << 1) as u16); - // 7-bit addressing mode - w.add10().clear_bit(); - // Set transfer direction to read - w.rd_wrn().set_bit(); - // Automatic end mode - w.autoend().set_bit(); - w.reload().clear_bit(); - // Start transfer - w.start().set_bit() - }); + pub fn release(self) -> (I2C, SDA, SCL) { + (self.i2c, self.sda.release(), self.scl.release()) + } +} - idx = 0; - loop { - // Wait until we have received something. Handle all state in busy_wait macro - busy_wait!(self.i2c, rxne, bit_is_set, idx, rcvlen); - if idx < rcvlen { - rcv_buffer[idx] = self.i2c.rxdr().read().rxdata().bits(); - idx +=1; - } - } +impl I2c { + pub fn write_read( + &mut self, + addr: u8, + snd_buffer: &[u8], + rcv_buffer: &mut [u8], + ) -> Result<(), Error> { + // TODO support transfers of more than 255 bytes + let sndlen = snd_buffer.len(); + let rcvlen = rcv_buffer.len(); + assert!(sndlen < 256 && sndlen > 0); + assert!(rcvlen < 256 && rcvlen > 0); + + // Wait for any previous address sequence to end automatically. + // This could be up to 50% of a bus cycle (ie. up to 0.5/freq) + while self.i2c.cr2().read().start().bit_is_set() {} + + // flush i2c tx register + self.i2c.isr().write(|w| w.txe().set_bit()); + + // Set START and prepare to send `bytes`. + // The START bit can be set even if the bus is BUSY or + // I2C is in slave mode. + self.i2c.cr2().write(|w| { + // Set number of bytes to transfer + w.nbytes().set(sndlen as u8); + // Set address to transfer to/from + w.sadd().set((addr << 1) as u16); + // 7-bit addressing mode + w.add10().clear_bit(); + // Set transfer direction to write + w.rd_wrn().clear_bit(); + // Software end mode + w.autoend().clear_bit(); + w.reload().clear_bit(); + // Start transfer + w.start().set_bit() + }); + let mut idx = 0; + // Wait until we are allowed to send data + // (START has been ACKed or last byte went through) + // macro will return false when the tc bit is set + for byte in snd_buffer { + busy_wait!(self.i2c, txis, bit_is_set, idx, sndlen); + // Put byte on the wire + self.i2c.txdr().write(|w| w.txdata().set(*byte)); + idx += 1; + } + // Wait until the write finishes before beginning to read. + let dummy = 0xFE; + busy_wait!(self.i2c, tc, bit_is_set, idx, dummy); + + // reSTART and prepare to receive bytes into `rcv_buffer` + self.i2c.cr2().write(|w| { + // Set number of bytes to transfer + w.nbytes().set(rcvlen as u8); + // Set address to transfer to/from + w.sadd().set((addr << 1) as u16); + // 7-bit addressing mode + w.add10().clear_bit(); + // Set transfer direction to read + w.rd_wrn().set_bit(); + // Automatic end mode + w.autoend().set_bit(); + w.reload().clear_bit(); + // Start transfer + w.start().set_bit() + }); + + idx = 0; + loop { + // Wait until we have received something. Handle all state in busy_wait macro + busy_wait!(self.i2c, rxne, bit_is_set, idx, rcvlen); + if idx < rcvlen { + rcv_buffer[idx] = self.i2c.rxdr().read().rxdata().bits(); + idx += 1; } } + } +} - impl I2c<$I2CX, SDA, SCL> { - pub fn write(&mut self, addr: u8, bytes: &[u8]) -> Result<(), Error> { - let buflen = bytes.len(); - assert!(buflen < 256 && buflen > 0); - - // Wait for any previous address sequence to end automatically. - // This could be up to 50% of a bus cycle (ie. up to 0.5/freq) - while self.i2c.cr2().read().start().bit_is_set() {}; - - self.i2c.cr2().modify(|_, w| { - // Start transfer - w.start().set_bit(); - // Set number of bytes to transfer - w.nbytes().set(buflen as u8); - // Set address to transfer to/from - w.sadd().set((addr << 1) as u16); - // Set transfer direction to write - w.rd_wrn().clear_bit(); - // Automatic end mode - w.autoend().set_bit(); - w.reload().clear_bit() - }); - - let mut idx = 0; - loop { - // Wait until we are allowed to send data, handle all state in busy_wait macro - busy_wait!(self.i2c, txis, bit_is_set, idx, buflen); +impl I2c { + pub fn write(&mut self, addr: u8, bytes: &[u8]) -> Result<(), Error> { + let buflen = bytes.len(); + assert!(buflen < 256 && buflen > 0); + + // Wait for any previous address sequence to end automatically. + // This could be up to 50% of a bus cycle (ie. up to 0.5/freq) + while self.i2c.cr2().read().start().bit_is_set() {} + + self.i2c.cr2().modify(|_, w| { + // Start transfer + w.start().set_bit(); + // Set number of bytes to transfer + w.nbytes().set(buflen as u8); + // Set address to transfer to/from + w.sadd().set((addr << 1) as u16); + // Set transfer direction to write + w.rd_wrn().clear_bit(); + // Automatic end mode + w.autoend().set_bit(); + w.reload().clear_bit() + }); + + let mut idx = 0; + loop { + // Wait until we are allowed to send data, handle all state in busy_wait macro + busy_wait!(self.i2c, txis, bit_is_set, idx, buflen); - // Put byte on the wire - if idx < buflen { - self.i2c.txdr().write(|w| w.txdata().set(bytes[idx])); - idx += 1; - } - } + // Put byte on the wire + if idx < buflen { + self.i2c.txdr().write(|w| w.txdata().set(bytes[idx])); + idx += 1; } } + } +} - impl I2c<$I2CX, SDA, SCL> { - pub fn read(&mut self, addr: u8, bytes: &mut [u8]) -> Result<(), Error> { - let buflen = bytes.len(); - // TODO support transfers of more than 255 bytes - assert!(buflen < 256 && buflen > 0); - - // Wait for any previous address sequence to end automatically. - // This could be up to 50% of a bus cycle (ie. up to 0.5/freq) - while self.i2c.cr2().read().start().bit_is_set() {}; - // Flush rxdr register - let _ = self.i2c.rxdr().read().rxdata().bits(); - - // Set START and prepare to receive bytes into `buffer`. - // The START bit can be set even if the bus - // is BUSY or I2C is in slave mode. - self.i2c.cr2().modify(|_, w| { - // Start transfer - w.start().set_bit(); - // Set number of bytes to transfer - w.nbytes().set(buflen as u8); - // Set address to transfer to/from - w.sadd().set((addr << 1) as u16); - // Set transfer direction to read - w.rd_wrn().set_bit(); - // automatic end mode - w.autoend().set_bit(); - w.reload().clear_bit() - }); - let mut idx = 0; - loop { - // Wait until we have received something - busy_wait!(self.i2c, rxne, bit_is_set, idx, buflen); - if idx < buflen { - bytes[idx] = self.i2c.rxdr().read().rxdata().bits(); - idx +=1; - } - } +impl I2c { + pub fn read(&mut self, addr: u8, bytes: &mut [u8]) -> Result<(), Error> { + let buflen = bytes.len(); + // TODO support transfers of more than 255 bytes + assert!(buflen < 256 && buflen > 0); + + // Wait for any previous address sequence to end automatically. + // This could be up to 50% of a bus cycle (ie. up to 0.5/freq) + while self.i2c.cr2().read().start().bit_is_set() {} + // Flush rxdr register + let _ = self.i2c.rxdr().read().rxdata().bits(); + + // Set START and prepare to receive bytes into `buffer`. + // The START bit can be set even if the bus + // is BUSY or I2C is in slave mode. + self.i2c.cr2().modify(|_, w| { + // Start transfer + w.start().set_bit(); + // Set number of bytes to transfer + w.nbytes().set(buflen as u8); + // Set address to transfer to/from + w.sadd().set((addr << 1) as u16); + // Set transfer direction to read + w.rd_wrn().set_bit(); + // automatic end mode + w.autoend().set_bit(); + w.reload().clear_bit() + }); + let mut idx = 0; + loop { + // Wait until we have received something + busy_wait!(self.i2c, rxne, bit_is_set, idx, buflen); + if idx < buflen { + bytes[idx] = self.i2c.rxdr().read().rxdata().bits(); + idx += 1; } } + } +} - impl I2cSlave for I2c<$I2CX, SDA, SCL> { - fn slave_sbc(&mut self, sbc_enabled: bool) { - // Enable Slave byte control - self.i2c.cr1().modify(|_, w| w.sbc().bit(sbc_enabled) ); - } +impl I2cSlave for I2c { + fn slave_sbc(&mut self, sbc_enabled: bool) { + // Enable Slave byte control + self.i2c.cr1().modify(|_, w| w.sbc().bit(sbc_enabled)); + } - fn slave_addressed(&mut self) -> Result, Error> { - if self.i2c.isr().read().addr().bit_is_set() { - let isr = self.i2c.isr().read(); - let current_address = isr.addcode().bits() as u16; - - // if the dir bit is set it is a master write slave read operation - let direction = if isr.dir().bit_is_set() { - I2cDirection::MasterReadSlaveWrite - } else { - I2cDirection::MasterWriteSlaveRead - }; - // do not yet release the clock stretching here. - // In the slave read function the nbytes is send, for this the addr bit must be set - Ok(Some((current_address, direction))) + fn slave_addressed(&mut self) -> Result, Error> { + if self.i2c.isr().read().addr().bit_is_set() { + let isr = self.i2c.isr().read(); + let current_address = isr.addcode().bits() as u16; + + // if the dir bit is set it is a master write slave read operation + let direction = if isr.dir().bit_is_set() { + I2cDirection::MasterReadSlaveWrite + } else { + I2cDirection::MasterWriteSlaveRead + }; + // do not yet release the clock stretching here. + // In the slave read function the nbytes is send, for this the addr bit must be set + Ok(Some((current_address, direction))) + } else { + Ok(None) + } + } - } else { - Ok(None) - } + fn slave_wait_addressed(&mut self) -> Result<(u16, I2cDirection), Error> { + loop { + if let Some(res) = self.slave_addressed()? { + return Ok(res); } + } + } - fn slave_wait_addressed(&mut self) -> Result<(u16, I2cDirection), Error> { - loop { - if let Some(res) = self.slave_addressed()? { - return Ok(res) - } - } + fn slave_write(&mut self, bytes: &[u8]) -> Result<(), Error> { + let buflen = bytes.len(); + // TODO support transfers of more than 255 bytes + assert!(buflen < 256 && buflen > 0); + + // Set the nbytes and prepare to send bytes into `buffer`. + self.i2c.cr2().modify(|_, w| { + w.nbytes().set(buflen as u8); + w.reload().clear_bit() + }); + // flush i2c tx register + self.i2c.isr().write(|w| w.txe().set_bit()); + // end address phase, release clock stretching + self.i2c.icr().write(|w| w.addrcf().set_bit()); + + let mut idx = 0; + loop { + // wait until we are allowed to send the byte. Handle all state in macro + busy_wait!(self.i2c, txis, bit_is_set, idx, buflen); + + // Put byte on the wire + if idx < buflen { + self.i2c.txdr().write(|w| w.txdata().set(bytes[idx])); + idx += 1; + } else { + // we will never reach here. In case the master wants to read more than buflen + // the hardware will send 0xFF + // Also means that on slave side we cannot detect this error case + self.i2c.txdr().write(|w| w.txdata().set(0x21)); } + } + } - fn slave_write(&mut self, bytes: &[u8]) -> Result<(), Error> { - let buflen = bytes.len(); - // TODO support transfers of more than 255 bytes - assert!(buflen < 256 && buflen > 0); - - // Set the nbytes and prepare to send bytes into `buffer`. - self.i2c.cr2().modify(|_, w| { - w.nbytes().set( buflen as u8); - w.reload().clear_bit() - }); - // flush i2c tx register - self.i2c.isr().write(|w| w.txe().set_bit()); - // end address phase, release clock stretching - self.i2c.icr().write(|w| w.addrcf().set_bit() ); - - let mut idx = 0; - loop { - // wait until we are allowed to send the byte. Handle all state in macro - busy_wait!(self.i2c, txis, bit_is_set, idx, buflen); - - // Put byte on the wire - if idx < buflen { - self.i2c.txdr().write(|w| w.txdata().set(bytes[idx])); - idx += 1; - } else { - // we will never reach here. In case the master wants to read more than buflen - // the hardware will send 0xFF - // Also means that on slave side we cannot detect this error case - self.i2c.txdr().write(|w| w.txdata().set(0x21)); - } - } - } + fn slave_read(&mut self, bytes: &mut [u8]) -> Result<(), Error> { + let buflen = bytes.len(); + // TODO support transfers of more than 255 bytes + assert!(buflen < 256 && buflen > 0); + + // Set the nbytes START and prepare to receive bytes into `buffer`. + self.i2c.cr2().modify(|_, w| { + // Set number of bytes to transfer: maximum as all incoming bytes will be ACK'ed + w.nbytes().set(buflen as u8); + // during sending nbytes automatically send a ACK, stretch clock after last byte + w.reload().set_bit() + }); + // end address phase, release clock stretching + self.i2c.icr().write(|w| w.addrcf().set_bit()); + flush_rxdr!(self.i2c); + + let mut idx = 0; + loop { + // Wait until we have received something. + busy_wait!(self.i2c, rxne, bit_is_set, idx, buflen); - fn slave_read(&mut self, bytes: &mut [u8]) -> Result<(), Error> { - let buflen = bytes.len(); - // TODO support transfers of more than 255 bytes - assert!(buflen < 256 && buflen > 0); - - // Set the nbytes START and prepare to receive bytes into `buffer`. - self.i2c.cr2().modify(|_, w| { - // Set number of bytes to transfer: maximum as all incoming bytes will be ACK'ed - w.nbytes().set(buflen as u8); - // during sending nbytes automatically send a ACK, stretch clock after last byte - w.reload().set_bit() - }); - // end address phase, release clock stretching - self.i2c.icr().write(|w| - w.addrcf().set_bit() - ); - flush_rxdr!(self.i2c); - - let mut idx = 0; - loop { - // Wait until we have received something. - busy_wait!(self.i2c, rxne, bit_is_set, idx, buflen); - - // read byte from wire - if idx < buflen { - bytes[idx] = self.i2c.rxdr().read().rxdata().bits(); - idx += 1; - } - } + // read byte from wire + if idx < buflen { + bytes[idx] = self.i2c.rxdr().read().rxdata().bits(); + idx += 1; } } + } +} - impl hal::i2c::ErrorType for I2c<$I2CX, SDA, SCL> { - type Error = Error; - } +impl hal::i2c::ErrorType for I2c { + type Error = Error; +} - impl hal::i2c::I2c for I2c<$I2CX, SDA, SCL> { - fn transaction( - &mut self, - address: hal::i2c::SevenBitAddress, - operations: &mut [hal::i2c::Operation<'_>], - ) -> Result<(), Self::Error> { - for op in operations { - match op { - hal::i2c::Operation::Read(buffer) => { - self.read(address, buffer)?; - } - hal::i2c::Operation::Write(buffer) => { - self.write(address, buffer)?; - } - } +impl hal::i2c::I2c for I2c { + fn transaction( + &mut self, + address: hal::i2c::SevenBitAddress, + operations: &mut [hal::i2c::Operation<'_>], + ) -> Result<(), Self::Error> { + for op in operations { + match op { + hal::i2c::Operation::Read(buffer) => { + self.read(address, buffer)?; + } + hal::i2c::Operation::Write(buffer) => { + self.write(address, buffer)?; } - Ok(()) } } + Ok(()) + } +} - impl I2cPeripheral for I2c<$I2CX, SDA, SCL> where - SDA: SDAPin<$I2CX>, - SCL: SCLPin<$I2CX> - { - type Error = Error; - - fn poll(&mut self) -> Result, Self::Error> { - self.slave_addressed().map(|event| { - event.map(|(addr, dir)| match dir { - I2cDirection::MasterWriteSlaveRead => I2cPeripheralEvent::Read(addr as _), - I2cDirection::MasterReadSlaveWrite => I2cPeripheralEvent::Write(addr as _), - }) - }) - } +impl I2cPeripheral for I2c +where + SDA: SDAPin, + SCL: SCLPin, +{ + type Error = Error; + + fn poll(&mut self) -> Result, Self::Error> { + self.slave_addressed().map(|event| { + event.map(|(addr, dir)| match dir { + I2cDirection::MasterWriteSlaveRead => I2cPeripheralEvent::Read(addr as _), + I2cDirection::MasterReadSlaveWrite => I2cPeripheralEvent::Write(addr as _), + }) + }) + } - fn rx(&mut self, buf: &mut [u8]) -> Result<(), Self::Error> { - self.slave_sbc(false); - self.slave_read(buf) - } + fn rx(&mut self, buf: &mut [u8]) -> Result<(), Self::Error> { + self.slave_sbc(false); + self.slave_read(buf) + } - fn tx(&mut self, buf: &[u8]) -> Result<(), Self::Error> { - self.slave_sbc(true); - self.slave_write(buf) - } + fn tx(&mut self, buf: &[u8]) -> Result<(), Self::Error> { + self.slave_sbc(true); + self.slave_write(buf) + } - fn flush(&mut self) -> Result<(), Self::Error> { - self.clear_irq(i2c::Event::Rxne); - self.clear_irq(i2c::Event::AddressMatch); - Ok(()) - } - } + fn flush(&mut self) -> Result<(), Self::Error> { + self.clear_irq(i2c::Event::Rxne); + self.clear_irq(i2c::Event::AddressMatch); + Ok(()) } } i2c!( - I2C1, - i2c1, + pac::I2C1, sda: [ PA10>, PB7>, @@ -570,8 +568,7 @@ i2c!( ); i2c!( - I2C2, - i2c2, + pac::I2C2, sda: [ PA12>, PB11>, diff --git a/src/i2c/mod.rs b/src/i2c/mod.rs index 11e6500..fe7c58b 100644 --- a/src/i2c/mod.rs +++ b/src/i2c/mod.rs @@ -9,7 +9,7 @@ pub use nonblocking::*; pub mod config; -use crate::rcc::*; +use crate::rcc::{self, Rcc}; pub use config::Config; use hal::i2c::{ErrorKind, NoAcknowledgeSource}; @@ -81,6 +81,14 @@ impl hal::i2c::Error for Error { } } +pub trait Instance: + crate::Sealed + + core::ops::Deref + + rcc::Enable + + rcc::Reset +{ +} + /// I2C SDA pin pub trait SDAPin { fn setup(&self); @@ -93,17 +101,17 @@ pub trait SCLPin { fn release(self) -> Self; } -pub trait I2cExt { +pub trait I2cExt: Sized { fn i2c( self, sda: SDA, scl: SCL, config: impl Into, rcc: &mut Rcc, - ) -> I2c + ) -> I2c where - SDA: SDAPin, - SCL: SCLPin; + SDA: SDAPin, + SCL: SCLPin; } /// I2C abstraction diff --git a/src/i2c/nonblocking.rs b/src/i2c/nonblocking.rs index 2ee9e7b..c488a6a 100644 --- a/src/i2c/nonblocking.rs +++ b/src/i2c/nonblocking.rs @@ -1,10 +1,10 @@ //! I2C +use super::config::Config; +use super::{EndMarker, Error, I2c, I2cDirection, I2cExt, I2cResult, Instance, SCLPin, SDAPin}; use crate::gpio::*; use crate::gpio::{AltFunction, OpenDrain, Output}; -use crate::i2c::config::Config; -use crate::i2c::{EndMarker, Error, I2c, I2cDirection, I2cExt, I2cResult, SCLPin, SDAPin}; -use crate::rcc::*; -use crate::stm32::{I2C1, I2C2}; +use crate::rcc::Rcc; +use crate::stm32 as pac; use nb::Error::{Other, WouldBlock}; pub trait I2cControl { @@ -34,7 +34,7 @@ pub trait I2cControl { /// /// Each function will first check the status of the bus. If busy it will return BusyWait /// Wrap the function in the block! macro to make it blocking -/// +/// /// The actual work is done in a separate function: check_isr_flags, see the I2cControl trait /// Wrap this function in the block! macro to make it blocking /// @@ -100,7 +100,7 @@ macro_rules! flush_rxdr { } macro_rules! i2c { - ($I2CX:ident, $i2cx:ident, + ($I2CX:ty, sda: [ $($PSDA:ty,)+ ], scl: [ $($PSCL:ty,)+ ], ) => { @@ -127,485 +127,501 @@ macro_rules! i2c { } } )+ + } +} - impl I2cExt<$I2CX> for $I2CX { - fn i2c( - self, - sda: SDA, - scl: SCL, - config: impl Into, - rcc: &mut Rcc, - ) -> I2c<$I2CX, SDA, SCL> - where - SDA: SDAPin<$I2CX>, - SCL: SCLPin<$I2CX>, - { - I2c::$i2cx(self, sda, scl, config, rcc) - } - } - - impl I2c<$I2CX, SDA, SCL> where - SDA: SDAPin<$I2CX>, - SCL: SCLPin<$I2CX> - { - pub fn $i2cx(i2c: $I2CX, sda: SDA, scl: SCL, config: impl Into, rcc: &mut Rcc) -> Self - where - SDA: SDAPin<$I2CX>, - SCL: SCLPin<$I2CX>, - { - let config = config.into(); - $I2CX::enable(rcc); - $I2CX::reset(rcc); - - // Make sure the I2C unit is disabled so we can configure it - i2c.cr1().modify(|_, w| w.pe().clear_bit()); - - // Setup protocol timings - let timing_bits = config.timing_bits(rcc.clocks.apb_clk); - i2c.timingr().write(|w| unsafe { w.bits(timing_bits) }); - - // Enable the I2C processing - i2c.cr1().modify(|_, w| unsafe { - w.pe() - .set_bit() - .dnf() - .bits(config.digital_filter) - .anfoff() - .bit(!config.analog_filter) - }); - - if config.slave_address_1 > 0 { - i2c.oar1().write(|w| unsafe { - w.oa1().bits(config.slave_address_1) - .oa1mode().bit(config.address_11bits) - .oa1en().set_bit() - }); - // Enable acknowlidge control - i2c.cr1().modify(|_, w| w.sbc().set_bit()); - } - - if config.slave_address_2 > 0 { - i2c.oar2().write(|w| unsafe { - w.oa2msk().bits(config.slave_address_mask as u8) - .oa2().bits(config.slave_address_2) - .oa2en().set_bit() - }); - // Enable acknowlidge control - i2c.cr1().modify(|_, w| w.sbc().set_bit()); - } +impl I2cExt for I2C { + fn i2c( + self, + sda: SDA, + scl: SCL, + config: impl Into, + rcc: &mut Rcc, + ) -> I2c + where + SDA: SDAPin, + SCL: SCLPin, + { + I2c::new(self, sda, scl, config, rcc) + } +} - // Enable pins - sda.setup(); - scl.setup(); - I2c { - i2c, - sda, - scl, - address:0, - watchdog:0, - index: 0, - length:0, - errors:0, - length_write_read:0, - data:[0_u8;255], - current_direction: I2cDirection::MasterReadSlaveWrite, - } - } +impl I2c +where + SDA: SDAPin, + SCL: SCLPin, +{ + pub fn new(i2c: I2C, sda: SDA, scl: SCL, config: impl Into, rcc: &mut Rcc) -> Self + where + SDA: SDAPin, + SCL: SCLPin, + { + let config = config.into(); + I2C::enable(rcc); + I2C::reset(rcc); + + // Make sure the I2C unit is disabled so we can configure it + i2c.cr1().modify(|_, w| w.pe().clear_bit()); + + // Setup protocol timings + let timing_bits = config.timing_bits(rcc.clocks.apb_clk); + i2c.timingr().write(|w| unsafe { w.bits(timing_bits) }); + + // Enable the I2C processing + i2c.cr1().modify(|_, w| unsafe { + w.pe().set_bit(); + w.dnf().bits(config.digital_filter); + w.anfoff().bit(!config.analog_filter) + }); + + if config.slave_address_1 > 0 { + i2c.oar1().write(|w| unsafe { + w.oa1() + .bits(config.slave_address_1) + .oa1mode() + .bit(config.address_11bits) + .oa1en() + .set_bit() + }); + // Enable acknowlidge control + i2c.cr1().modify(|_, w| w.sbc().set_bit()); + } - pub fn release(self) -> ($I2CX, SDA, SCL) { - (self.i2c, self.sda.release(), self.scl.release()) - } + if config.slave_address_2 > 0 { + i2c.oar2().write(|w| unsafe { + w.oa2msk() + .bits(config.slave_address_mask as u8) + .oa2() + .bits(config.slave_address_2) + .oa2en() + .set_bit() + }); + // Enable acknowlidge control + i2c.cr1().modify(|_, w| w.sbc().set_bit()); } - impl I2cControl for I2c<$I2CX, SDA, SCL> { - /// Starts listening for an interrupt event - fn listen(&mut self) { - self.i2c.cr1().modify(|_, w| - w.txie().set_bit() - .addrie().set_bit() - .rxie().set_bit() - .nackie().set_bit() - .stopie().set_bit() - .errie().set_bit() - .tcie().set_bit() - ); - } + // Enable pins + sda.setup(); + scl.setup(); + I2c { + i2c, + sda, + scl, + address: 0, + watchdog: 0, + index: 0, + length: 0, + errors: 0, + length_write_read: 0, + data: [0_u8; 255], + current_direction: I2cDirection::MasterReadSlaveWrite, + } + } + pub fn release(self) -> (I2C, SDA, SCL) { + (self.i2c, self.sda.release(), self.scl.release()) + } +} - /// Stop listening for an interrupt event - fn unlisten(&mut self) { - self.i2c.cr1().modify(|_, w| - w.txie().clear_bit() - .rxie().clear_bit() - .addrie().clear_bit() - .nackie().clear_bit() - .stopie().clear_bit() - .tcie().clear_bit() - .errie().clear_bit() - ); - } +impl I2cControl for I2c { + /// Starts listening for an interrupt event + fn listen(&mut self) { + self.i2c.cr1().modify(|_, w| { + w.txie().set_bit(); + w.addrie().set_bit(); + w.rxie().set_bit(); + w.nackie().set_bit(); + w.stopie().set_bit(); + w.errie().set_bit(); + w.tcie().set_bit() + }); + } - /// get the global error counter. Reset to 0 after read - fn get_errors_reset(&mut self) -> usize { - let result = self.errors; - self.errors = 0; - result - } + /// Stop listening for an interrupt event + fn unlisten(&mut self) { + self.i2c.cr1().modify(|_, w| { + w.txie().clear_bit(); + w.rxie().clear_bit(); + w.addrie().clear_bit(); + w.nackie().clear_bit(); + w.stopie().clear_bit(); + w.tcie().clear_bit(); + w.errie().clear_bit() + }); + } - /// optional function - /// If used call this function once per 10th second. After 10 calls (after a second) - /// i2c will be forcefully reset, if the watchdog counter is still greater than zero - fn execute_watchdog(&mut self) { - match self.watchdog { - 0 => return, - 1 => { - self.errors += 1; - self.watchdog = 0; - // Disable I2C processing, resetting all hardware state machines - self.i2c.cr1().modify(|_, w| w.pe().clear_bit()); - // force enough wait states for the pe clear - let _ = self.i2c.cr1().read(); - // Enable the I2C processing again - self.i2c.cr1().modify(|_, w| w.pe().set_bit()); - }, - _ => self.watchdog -= 1, - } - } + /// get the global error counter. Reset to 0 after read + fn get_errors_reset(&mut self) -> usize { + let result = self.errors; + self.errors = 0; + result + } - /// Check the isr flags. If the transaction still is not finished - /// This funcion can be called inside the block! macro for blocking mode, - /// or inside an I2C interrupt, in case the isr is enalbed - fn check_isr_flags(&mut self) -> nb::Result< I2cResult, Error>{ - let isr = self.i2c.isr().read(); - - if isr.berr().bit_is_set() { - self.i2c.icr().write(|w| w.berrcf().set_bit()); - self.errors += 1; - return Err(Other(Error::BusError)) - } else if isr.arlo().bit_is_set() { - self.i2c.icr().write(|w| w.arlocf().set_bit()); - return Err(Other(Error::ArbitrationLost)) - } else if isr.nackf().bit_is_set() { - self.i2c.icr().write(|w| w.nackcf().set_bit()); - // Make one extra loop to wait on the stop condition - return Err(WouldBlock) - } else if isr.txis().bit_is_set() { - // Put byte on the wire - if self.index < self.length { - self.i2c.txdr().write(|w| unsafe { w.txdata().bits(self.data[self.index]) }); - self.index += 1; // ok previous byte is send now - } - return Err(WouldBlock) - } else if isr.rxne().bit_is_set() { - // read byte from the wire - if self.index < self.length { - self.data[self.index] = self.i2c.rxdr().read().rxdata().bits(); - self.index += 1; - } else { - // anyway read the result to clear the rxne flag - flush_rxdr!(self.i2c); - } - return Err(WouldBlock) - } else if isr.stopf().bit_is_set() { - // Clear the stop condition flag - self.i2c.icr().write(|w| w.stopcf().set_bit()); - // Disable the watchdog - self.watchdog = 0; - if self.index == 0 { - self.errors += 1; - return Err(Other(Error::Nack)) - } else { - // figure out the direction - let direction = if isr.dir().bit_is_set() { - I2cDirection::MasterReadSlaveWrite - } else { - I2cDirection::MasterWriteSlaveRead - }; - let index = self.index; - // Clear the length so we don't think there is still data when we reach the address phase - self.length = self.data.len(); - self.index = 0; - // return the actual amount of data (self.index), not the requested (self.length) - // application must evaluate the size of the frame - return Ok( I2cResult::Data(self.address, direction, &self.data[0..index], EndMarker::Stop)) - } - } else if isr.tc().bit_is_set() { - // This condition Will only happen when autoend is 0 in master mode (write with subb addressing) - // Flag is reset by a start or stop condition. - // no stop condition will be generated in this transaction so evaluate the result here - if self.index < self.length { - self.index += 1; // ok previous byte is send now - } - if self.index == self.length { - // ok start the second part of the transaction - // reSTART and prepare to receive bytes into `rcv_buffer` - self.length = self.length_write_read; - self.length_write_read = 0; - self.index = 0; - self.i2c.cr2().write(|w| unsafe { - w - // Set number of bytes to transfer - .nbytes().bits(self.length as u8) - // Set address to transfer to/from - .sadd().bits((self.address << 1) as u16) - // 7-bit addressing mode - .add10().clear_bit() - // Set transfer direction to read - .rd_wrn().set_bit() - // Automatic end mode - .autoend().set_bit() - .reload().clear_bit() - // Start transfer - .start().set_bit() - }); - // not yet ready here - return Err(WouldBlock) - } else if self.index == 0 { - self.i2c.cr2().modify(|_, w| w.stop().set_bit()); - self.errors += 1; - return Err(Other(Error::Nack)) - } else { - self.i2c.cr2().modify(|_, w| w.stop().set_bit()); - self.errors += 1; - return Err(Other(Error::IncorrectFrameSize(self.index))) - } - } else if isr.tcr().bit_is_set() { - // This condition Will only happen when reload == 1 and sbr == 1 (slave) and nbytes was written. - // Send a NACK, set nbytes to clear tcr flag - self.i2c.cr2().modify(|_, w| unsafe { - w.nack().set_bit().nbytes().bits( 1 as u8) - }); - // Make one extra loop here to wait on the stop condition - return Err(WouldBlock) - } else if isr.addr().bit_is_set() { - // Handle the case where there was no stop bit (repeated start) - // In this case there will be data on the buffer which still needs to be delivered - if self.current_direction == I2cDirection::MasterWriteSlaveRead && self.index >= 1 { - let index = self.index; - self.index = 0; - return Ok( I2cResult::Data(self.address, self.current_direction, &self.data[0..index], EndMarker::StartRepeat)) - } - // handle the slave device case, addressed by a master - let current_address = isr.addcode().bits() as u16; - self.address = current_address; - // guard against misbehavior - self.watchdog = 10; - - // figure out the direction. - let direction = if isr.dir().bit_is_set() { - I2cDirection::MasterReadSlaveWrite - } else { - // Start the master write slave read transaction fully automatically here - // Set the nbytes to the max size and prepare to receive bytes into `buffer`. - self.length = self.data.len(); - self.index = 0; - self.i2c.cr2().modify(|_, w| unsafe { - // Set number of bytes to transfer: as many as internal buffer - w.nbytes().bits(self.length as u8) - // during sending nbytes automatically send a ACK, stretch clock after last byte - .reload().set_bit() - }); - // end address phase, release clock stretching - self.i2c.icr().write(|w| w.addrcf().set_bit()); - // return result - I2cDirection::MasterWriteSlaveRead - }; - self.current_direction = direction; - // do not yet release the clock stretching here - return Ok(I2cResult::Addressed(current_address, direction)) - } - return Err(WouldBlock) + /// optional function + /// If used call this function once per 10th second. After 10 calls (after a second) + /// i2c will be forcefully reset, if the watchdog counter is still greater than zero + fn execute_watchdog(&mut self) { + match self.watchdog { + 0 => return, + 1 => { + self.errors += 1; + self.watchdog = 0; + // Disable I2C processing, resetting all hardware state machines + self.i2c.cr1().modify(|_, w| w.pe().clear_bit()); + // force enough wait states for the pe clear + let _ = self.i2c.cr1().read(); + // Enable the I2C processing again + self.i2c.cr1().modify(|_, w| w.pe().set_bit()); } + _ => self.watchdog -= 1, } + } - impl I2cMaster for I2c<$I2CX, SDA, SCL> { - fn master_write(&mut self, addr: u16, data: &[u8]) -> nb::Result<(), Error>{ - // Check if the bus is free - if self.i2c.cr2().read().start().bit_is_set() { - return Err(nb::Error::WouldBlock) + /// Check the isr flags. If the transaction still is not finished + /// This funcion can be called inside the block! macro for blocking mode, + /// or inside an I2C interrupt, in case the isr is enalbed + fn check_isr_flags(&mut self) -> nb::Result { + let isr = self.i2c.isr().read(); + + if isr.berr().bit_is_set() { + self.i2c.icr().write(|w| w.berrcf().set_bit()); + self.errors += 1; + return Err(Other(Error::BusError)); + } else if isr.arlo().bit_is_set() { + self.i2c.icr().write(|w| w.arlocf().set_bit()); + return Err(Other(Error::ArbitrationLost)); + } else if isr.nackf().bit_is_set() { + self.i2c.icr().write(|w| w.nackcf().set_bit()); + // Make one extra loop to wait on the stop condition + return Err(WouldBlock); + } else if isr.txis().bit_is_set() { + // Put byte on the wire + if self.index < self.length { + self.i2c + .txdr() + .write(|w| unsafe { w.txdata().bits(self.data[self.index]) }); + self.index += 1; // ok previous byte is send now + } + return Err(WouldBlock); + } else if isr.rxne().bit_is_set() { + // read byte from the wire + if self.index < self.length { + self.data[self.index] = self.i2c.rxdr().read().rxdata().bits(); + self.index += 1; + } else { + // anyway read the result to clear the rxne flag + flush_rxdr!(self.i2c); + } + return Err(WouldBlock); + } else if isr.stopf().bit_is_set() { + // Clear the stop condition flag + self.i2c.icr().write(|w| w.stopcf().set_bit()); + // Disable the watchdog + self.watchdog = 0; + if self.index == 0 { + self.errors += 1; + return Err(Other(Error::Nack)); + } else { + // figure out the direction + let direction = if isr.dir().bit_is_set() { + I2cDirection::MasterReadSlaveWrite + } else { + I2cDirection::MasterWriteSlaveRead }; - self.watchdog = 10; - let buflen = data.len(); - assert!(buflen < 256 && buflen > 0); - self.length = buflen; - self.data[..buflen].copy_from_slice(data); + let index = self.index; + // Clear the length so we don't think there is still data when we reach the address phase + self.length = self.data.len(); self.index = 0; - self.address = addr; + // return the actual amount of data (self.index), not the requested (self.length) + // application must evaluate the size of the frame + return Ok(I2cResult::Data( + self.address, + direction, + &self.data[0..index], + EndMarker::Stop, + )); + } + } else if isr.tc().bit_is_set() { + // This condition Will only happen when autoend is 0 in master mode (write with subb addressing) + // Flag is reset by a start or stop condition. + // no stop condition will be generated in this transaction so evaluate the result here + if self.index < self.length { + self.index += 1; // ok previous byte is send now + } + if self.index == self.length { + // ok start the second part of the transaction + // reSTART and prepare to receive bytes into `rcv_buffer` + self.length = self.length_write_read; self.length_write_read = 0; - - self.i2c.cr2().modify(|_, w| unsafe { - w - // Start transfer - .start().set_bit() - // Set number of bytes to transfer - .nbytes().bits(buflen as u8) - // Set address to transfer to/from - .sadd().bits((addr << 1) as u16) - // Set transfer direction to write - .rd_wrn().clear_bit() - // Automatic end mode - .autoend().bit(true) - .reload().clear_bit() + self.index = 0; + self.i2c.cr2().write(|w| unsafe { + // Set number of bytes to transfer + w.nbytes().bits(self.length as u8); + // Set address to transfer to/from + w.sadd().bits((self.address << 1) as u16); + // 7-bit addressing mode + w.add10().clear_bit(); + // Set transfer direction to read + w.rd_wrn().set_bit(); + // Automatic end mode + w.autoend().set_bit(); + w.reload().clear_bit(); + // Start transfer + w.start().set_bit() }); - // in non-blocking mode the result is not yet available - Ok(()) + // not yet ready here + return Err(WouldBlock); + } else if self.index == 0 { + self.i2c.cr2().modify(|_, w| w.stop().set_bit()); + self.errors += 1; + return Err(Other(Error::Nack)); + } else { + self.i2c.cr2().modify(|_, w| w.stop().set_bit()); + self.errors += 1; + return Err(Other(Error::IncorrectFrameSize(self.index))); } - - fn master_write_read(&mut self, addr: u16, data: &[u8], read_len: u8) -> nb::Result<(), Error>{ - // Check if the bus is free - if self.i2c.cr2().read().start().bit_is_set() { - return Err(nb::Error::WouldBlock) - }; - self.watchdog = 10; - let buflen = data.len(); - assert!(buflen < 256 && buflen > 0); - self.length = buflen; - self.data[..buflen].copy_from_slice(data); + } else if isr.tcr().bit_is_set() { + // This condition Will only happen when reload == 1 and sbr == 1 (slave) and nbytes was written. + // Send a NACK, set nbytes to clear tcr flag + self.i2c.cr2().modify(|_, w| unsafe { + w.nack().set_bit(); + w.nbytes().bits(1 as u8) + }); + // Make one extra loop here to wait on the stop condition + return Err(WouldBlock); + } else if isr.addr().bit_is_set() { + // Handle the case where there was no stop bit (repeated start) + // In this case there will be data on the buffer which still needs to be delivered + if self.current_direction == I2cDirection::MasterWriteSlaveRead && self.index >= 1 { + let index = self.index; self.index = 0; - self.address = addr; - self.length_write_read = read_len as usize; - - self.i2c.cr2().modify(|_, w| unsafe { - w - // Start transfer - .start().set_bit() - // Set number of bytes to transfer - .nbytes().bits(buflen as u8) - // Set address to transfer to/from - .sadd().bits((addr << 1) as u16) - // Set transfer direction to write - .rd_wrn().clear_bit() - // Automatic end mode - .autoend().bit(false) - .reload().clear_bit() - }); - // in non-blocking mode the result is not yet available - Ok(()) + return Ok(I2cResult::Data( + self.address, + self.current_direction, + &self.data[0..index], + EndMarker::StartRepeat, + )); } - - fn master_read(&mut self, addr: u16, length: u8) -> nb::Result<(), Error>{ - // Wait for any previous address sequence to end automatically. - // This could be up to 50% of a bus cycle (ie. up to 0.5/freq) - if self.i2c.cr2().read().start().bit_is_set() { - return Err(nb::Error::WouldBlock) - }; - // Flush rxdr register - self.watchdog = 10; - self.i2c.rxdr().read().rxdata().bits(); - self.length = length as usize; + // handle the slave device case, addressed by a master + let current_address = isr.addcode().bits() as u16; + self.address = current_address; + // guard against misbehavior + self.watchdog = 10; + + // figure out the direction. + let direction = if isr.dir().bit_is_set() { + I2cDirection::MasterReadSlaveWrite + } else { + // Start the master write slave read transaction fully automatically here + // Set the nbytes to the max size and prepare to receive bytes into `buffer`. + self.length = self.data.len(); self.index = 0; - self.address = addr; - - for i in 0.. length as usize { - self.data[i] = 0; - } - - // Set START and prepare to receive bytes into `buffer`. - // The START bit can be set even if the bus - // is BUSY or I2C is in slave mode. self.i2c.cr2().modify(|_, w| unsafe { - w - // Start transfer - .start().set_bit() - // Set number of bytes to transfer - .nbytes().bits(length as u8) - // Set address to transfer to/from - .sadd().bits((addr << 1) as u16) - // Set transfer direction to read - .rd_wrn().set_bit() - // automatic end mode - .autoend().set_bit() - .reload().clear_bit() + // Set number of bytes to transfer: as many as internal buffer + w.nbytes().bits(self.length as u8); + // during sending nbytes automatically send a ACK, stretch clock after last byte + w.reload().set_bit() }); - // in non-blocking mode the result is not yet available - Ok(()) - } + // end address phase, release clock stretching + self.i2c.icr().write(|w| w.addrcf().set_bit()); + // return result + I2cDirection::MasterWriteSlaveRead + }; + self.current_direction = direction; + // do not yet release the clock stretching here + return Ok(I2cResult::Addressed(current_address, direction)); + } + return Err(WouldBlock); + } +} - fn get_address(&self) -> u16 { - self.address - } +impl I2cMaster for I2c { + fn master_write(&mut self, addr: u16, data: &[u8]) -> nb::Result<(), Error> { + // Check if the bus is free + if self.i2c.cr2().read().start().bit_is_set() { + return Err(nb::Error::WouldBlock); + }; + self.watchdog = 10; + let buflen = data.len(); + assert!(buflen < 256 && buflen > 0); + self.length = buflen; + self.data[..buflen].copy_from_slice(data); + self.index = 0; + self.address = addr; + self.length_write_read = 0; + + self.i2c.cr2().modify(|_, w| unsafe { + // Start transfer + w.start().set_bit(); + // Set number of bytes to transfer + w.nbytes().bits(buflen as u8); + // Set address to transfer to/from + w.sadd().bits((addr << 1) as u16); + // Set transfer direction to write + w.rd_wrn().clear_bit(); + // Automatic end mode + w.autoend().bit(true); + w.reload().clear_bit() + }); + // in non-blocking mode the result is not yet available + Ok(()) + } + fn master_write_read(&mut self, addr: u16, data: &[u8], read_len: u8) -> nb::Result<(), Error> { + // Check if the bus is free + if self.i2c.cr2().read().start().bit_is_set() { + return Err(nb::Error::WouldBlock); + }; + self.watchdog = 10; + let buflen = data.len(); + assert!(buflen < 256 && buflen > 0); + self.length = buflen; + self.data[..buflen].copy_from_slice(data); + self.index = 0; + self.address = addr; + self.length_write_read = read_len as usize; + + self.i2c.cr2().modify(|_, w| unsafe { + // Start transfer + w.start().set_bit(); + // Set number of bytes to transfer + w.nbytes().bits(buflen as u8); + // Set address to transfer to/from + w.sadd().bits((addr << 1) as u16); + // Set transfer direction to write + w.rd_wrn().clear_bit(); + // Automatic end mode + w.autoend().bit(false); + w.reload().clear_bit() + }); + // in non-blocking mode the result is not yet available + Ok(()) + } - /// return a non mutable slice to the internal data, with the size of the last transaction - fn get_data(&self) -> &[u8] { - &self.data[0..self.length] - } + fn master_read(&mut self, addr: u16, length: u8) -> nb::Result<(), Error> { + // Wait for any previous address sequence to end automatically. + // This could be up to 50% of a bus cycle (ie. up to 0.5/freq) + if self.i2c.cr2().read().start().bit_is_set() { + return Err(nb::Error::WouldBlock); + }; + // Flush rxdr register + self.watchdog = 10; + self.i2c.rxdr().read().rxdata().bits(); + self.length = length as usize; + self.index = 0; + self.address = addr; + + for i in 0..length as usize { + self.data[i] = 0; } - impl I2cSlave for I2c<$I2CX, SDA, SCL> { - fn slave_sbc(&mut self, sbc_enabled: bool) { - // enable acknowlidge control - self.i2c.cr1().modify(|_, w| w.sbc().bit(sbc_enabled)); - } + // Set START and prepare to receive bytes into `buffer`. + // The START bit can be set even if the bus + // is BUSY or I2C is in slave mode. + self.i2c.cr2().modify(|_, w| unsafe { + // Start transfer + w.start().set_bit(); + // Set number of bytes to transfer + w.nbytes().bits(length as u8); + // Set address to transfer to/from + w.sadd().bits((addr << 1) as u16); + // Set transfer direction to read + w.rd_wrn().set_bit(); + // automatic end mode + w.autoend().set_bit(); + w.reload().clear_bit() + }); + // in non-blocking mode the result is not yet available + Ok(()) + } - fn set_address(&mut self, address: u16) { - self.i2c.oar1().write(|w| unsafe { - w.oa1().bits(address) - .oa1en().clear_bit() - }); - // set the 7 bits address - self.i2c.oar1().write(|w| unsafe { - w.oa1().bits(address) - .oa1mode().clear_bit() - .oa1en().set_bit() - }); - } + fn get_address(&self) -> u16 { + self.address + } - fn slave_write(&mut self, bytes: &[u8]) -> Result<(), Error> { - let buflen = bytes.len(); - // TODO support transfers of more than 255 bytes - assert!(buflen < 256 && buflen > 0); + /// return a non mutable slice to the internal data, with the size of the last transaction + fn get_data(&self) -> &[u8] { + &self.data[0..self.length] + } +} - self.length = buflen; - self.data[..buflen].copy_from_slice(bytes); - self.index = 0; +impl I2cSlave for I2c { + fn slave_sbc(&mut self, sbc_enabled: bool) { + // enable acknowlidge control + self.i2c.cr1().modify(|_, w| w.sbc().bit(sbc_enabled)); + } - // Set the nbytes and prepare to send bytes into `buffer`. - self.i2c.cr2().modify(|_, w| unsafe { - w.nbytes().bits( buflen as u8).reload().clear_bit() - }); - // flush i2c tx register - self.i2c.isr().write(|w| w.txe().set_bit()); - // end address phase, release clock stretching - self.i2c.icr().write(|w| w.addrcf().set_bit()); + fn set_address(&mut self, address: u16) { + self.i2c + .oar1() + .write(|w| unsafe { w.oa1().bits(address).oa1en().clear_bit() }); + // set the 7 bits address + self.i2c.oar1().write(|w| unsafe { + w.oa1() + .bits(address) + .oa1mode() + .clear_bit() + .oa1en() + .set_bit() + }); + } - // in non-blocking mode the result is not yet available - Ok(()) - } + fn slave_write(&mut self, bytes: &[u8]) -> Result<(), Error> { + let buflen = bytes.len(); + // TODO support transfers of more than 255 bytes + assert!(buflen < 256 && buflen > 0); + + self.length = buflen; + self.data[..buflen].copy_from_slice(bytes); + self.index = 0; + + // Set the nbytes and prepare to send bytes into `buffer`. + self.i2c + .cr2() + .modify(|_, w| unsafe { w.nbytes().bits(buflen as u8).reload().clear_bit() }); + // flush i2c tx register + self.i2c.isr().write(|w| w.txe().set_bit()); + // end address phase, release clock stretching + self.i2c.icr().write(|w| w.addrcf().set_bit()); + + // in non-blocking mode the result is not yet available + Ok(()) + } - fn get_address(&self) -> u16 { - self.address - } + fn get_address(&self) -> u16 { + self.address + } - /// return a non mutable slice to the internal data, with the size of the last transaction - fn get_data(&self) -> &[u8] { - &self.data[0..self.index] - } - } + /// return a non mutable slice to the internal data, with the size of the last transaction + fn get_data(&self) -> &[u8] { + &self.data[0..self.index] + } +} - impl hal::i2c::ErrorType for I2c<$I2CX, SDA, SCL> { - type Error = Error; - } +impl hal::i2c::ErrorType for I2c { + type Error = Error; +} - impl hal::i2c::I2c for I2c<$I2CX, SDA, SCL> { - fn transaction(&mut self, address: hal::i2c::SevenBitAddress, operations: &mut [hal::i2c::Operation<'_>]) -> Result<(), Self::Error> { - for op in operations { - match op { - hal::i2c::Operation::Read(buffer) => { - self.read(address, buffer)?; - } - hal::i2c::Operation::Write(buffer) => { - self.write(address, buffer)?; - } - } +impl hal::i2c::I2c for I2c { + fn transaction( + &mut self, + address: hal::i2c::SevenBitAddress, + operations: &mut [hal::i2c::Operation<'_>], + ) -> Result<(), Self::Error> { + for op in operations { + match op { + hal::i2c::Operation::Read(buffer) => { + self.read(address, buffer)?; + } + hal::i2c::Operation::Write(buffer) => { + self.write(address, buffer)?; } - Ok(()) } } + Ok(()) } } i2c!( - I2C1, - i2c1, + pac::I2C1, sda: [ PA10>, PB7>, @@ -619,8 +635,7 @@ i2c!( ); i2c!( - I2C2, - i2c2, + pac::I2C2, sda: [ PA12>, PB11>, diff --git a/src/serial/usart.rs b/src/serial/usart.rs index 7b3effe..9272d55 100644 --- a/src/serial/usart.rs +++ b/src/serial/usart.rs @@ -175,13 +175,13 @@ where } } -pub trait SerialExt { - fn usart>( +pub trait SerialExt: Sized { + fn usart( self, - pins: PINS, + pins: impl Pins, config: CONFIG, rcc: &mut Rcc, - ) -> Result, InvalidConfig>; + ) -> Result, InvalidConfig>; } macro_rules! uart_shared { @@ -443,10 +443,10 @@ macro_rules! uart_basic { ($USARTX:ident, $usartX:ident, $clk_mul:expr ) => { - impl SerialExt<$USARTX, BasicConfig> for $USARTX { - fn usart>( + impl SerialExt for $USARTX { + fn usart( self, - pins: PINS, + pins: impl Pins, config: BasicConfig, rcc: &mut Rcc, ) -> Result, InvalidConfig> { @@ -596,13 +596,13 @@ macro_rules! uart_full { ($USARTX:ident, $usartX:ident, $clk_mul:expr ) => { - impl SerialExt<$USARTX, FullConfig> for $USARTX { - fn usart>( + impl SerialExt for $USARTX { + fn usart( self, - pins: PINS, + pins: impl Pins, config: FullConfig, rcc: &mut Rcc, - ) -> Result, InvalidConfig> { + ) -> Result, InvalidConfig> { Serial::$usartX(self, pins, config, rcc) } } diff --git a/src/spi.rs b/src/spi.rs index 2745f65..454c86c 100644 --- a/src/spi.rs +++ b/src/spi.rs @@ -1,8 +1,9 @@ use crate::gpio::*; -use crate::rcc::*; -use crate::stm32::{SPI1, SPI2}; +use crate::rcc::{self, Rcc}; +use crate::stm32::{self as pac, spi1}; use crate::time::Hertz; use core::convert::Infallible; +use core::ptr; use embedded_hal::delay::DelayNs; use hal::digital; use hal::digital::OutputPin; @@ -36,6 +37,11 @@ impl hal::spi::Error for Error { } } +pub trait Instance: + crate::Sealed + core::ops::Deref + rcc::Enable + rcc::Reset +{ +} + /// A filler type for when the delay is unnecessary pub struct NoDelay; @@ -124,11 +130,13 @@ pub trait SpiExt: Sized { } macro_rules! spi { - ($SPIX:ident, $spiX:ident, + ($SPIX:ty, sck: [ $(($SCK:ty, $SCK_AF:expr),)+ ], miso: [ $(($MISO:ty, $MISO_AF:expr),)+ ], mosi: [ $(($MOSI:ty, $MOSI_AF:expr),)+ ], ) => { + impl Instance for $SPIX {} + impl PinSck<$SPIX> for NoSck { fn setup(&self) {} @@ -186,214 +194,219 @@ macro_rules! spi { } } )* + } +} - impl> SpiBus<$SPIX, PINS> { - pub fn $spiX( - spi: $SPIX, - pins: PINS, - mode: Mode, - speed: Hertz, - rcc: &mut Rcc - ) -> Self { - $SPIX::enable(rcc); - $SPIX::reset(rcc); - - // disable SS output - spi.cr2().write(|w| w.ssoe().clear_bit()); - - let br = match rcc.clocks.apb_clk / speed { - 0 => unreachable!(), - 1..=2 => 0b000, - 3..=5 => 0b001, - 6..=11 => 0b010, - 12..=23 => 0b011, - 24..=47 => 0b100, - 48..=95 => 0b101, - 96..=191 => 0b110, - _ => 0b111, - }; - - spi.cr2().write(|w| unsafe { - w.frxth().set_bit().ds().bits(0b111).ssoe().clear_bit() - }); - - // Enable pins - pins.setup(); - - #[rustfmt::skip] - spi.cr1().write(|w| { - w.cpha().bit(mode.phase == Phase::CaptureOnSecondTransition); - w.cpol().bit(mode.polarity == Polarity::IdleHigh); - w.mstr().set_bit(); - w.br().set(br); - w.lsbfirst().clear_bit(); - w.ssm().set_bit(); - w.ssi().set_bit(); - w.rxonly().clear_bit(); - w.crcl().clear_bit(); - w.bidimode().clear_bit(); - w.spe().set_bit() - }); - - SpiBus { spi, pins } - } - - pub fn exclusive(self, cs: CS, delay: DELAY) -> SpiDevice, CS, DELAY,> { - SpiDevice { - bus: self, - cs, - delay - } - } +impl> SpiBus { + pub fn new(spi: SPI, pins: PINS, mode: Mode, speed: Hertz, rcc: &mut Rcc) -> Self { + SPI::enable(rcc); + SPI::reset(rcc); + + // disable SS output + spi.cr2().write(|w| w.ssoe().clear_bit()); + + let br = match rcc.clocks.apb_clk / speed { + 0 => unreachable!(), + 1..=2 => 0b000, + 3..=5 => 0b001, + 6..=11 => 0b010, + 12..=23 => 0b011, + 24..=47 => 0b100, + 48..=95 => 0b101, + 96..=191 => 0b110, + _ => 0b111, + }; + + spi.cr2() + .write(|w| unsafe { w.frxth().set_bit().ds().bits(0b111).ssoe().clear_bit() }); + + // Enable pins + pins.setup(); + + spi.cr1().write(|w| { + w.cpha().bit(mode.phase == Phase::CaptureOnSecondTransition); + w.cpol().bit(mode.polarity == Polarity::IdleHigh); + w.mstr().set_bit(); + w.br().set(br); + w.lsbfirst().clear_bit(); + w.ssm().set_bit(); + w.ssi().set_bit(); + w.rxonly().clear_bit(); + w.crcl().clear_bit(); + w.bidimode().clear_bit(); + w.spe().set_bit() + }); + + SpiBus { spi, pins } + } - pub fn data_size(&mut self, nr_bits: u8) { - self.spi.cr2().modify(|_, w| unsafe { - w.ds().bits(nr_bits-1) - }); - } + pub fn exclusive( + self, + cs: CS, + delay: DELAY, + ) -> SpiDevice, CS, DELAY> { + SpiDevice { + bus: self, + cs, + delay, + } + } - pub fn half_duplex_enable(&mut self, enable: bool) { - self.spi.cr1().modify(|_, w| - w.bidimode().bit(enable) - ); - } + pub fn data_size(&mut self, nr_bits: u8) { + self.spi + .cr2() + .modify(|_, w| unsafe { w.ds().bits(nr_bits - 1) }); + } - pub fn half_duplex_output_enable(&mut self, enable: bool) { - self.spi.cr1().modify(|_, w| - w.bidioe().bit(enable) - ); - } + pub fn half_duplex_enable(&mut self, enable: bool) { + self.spi.cr1().modify(|_, w| w.bidimode().bit(enable)); + } - pub fn release(self) -> ($SPIX, PINS) { - (self.spi, self.pins.release()) - } - } + pub fn half_duplex_output_enable(&mut self, enable: bool) { + self.spi.cr1().modify(|_, w| w.bidioe().bit(enable)); + } - impl ErrorType for SpiDevice, CS, DELAY> { - type Error = Error; - } + pub fn release(self) -> (SPI, PINS) { + (self.spi, self.pins.release()) + } +} - impl spi::SpiDevice for SpiDevice, CS, DELAY> { - fn transaction(&mut self, operations: &mut [hal::spi::Operation<'_, u8>]) -> Result<(), Error> { - use crate::hal::spi::SpiBus; - self.cs.set_low().map_err(|_| Error::ChipSelectFault)?; - for op in operations { - match op { - spi::Operation::Read(read) => { self.bus.read(read)?; }, - spi::Operation::Write(write) => { self.bus.write(write)?; }, - spi::Operation::Transfer(write, read) => { self.bus.transfer(write, read)?; }, - spi::Operation::TransferInPlace(data) => { self.bus.transfer_in_place(data)?; }, - spi::Operation::DelayNs(ns) => { self.delay.delay_ns(*ns) }, - } +impl ErrorType + for SpiDevice, CS, DELAY> +{ + type Error = Error; +} +impl spi::SpiDevice + for SpiDevice, CS, DELAY> +{ + fn transaction(&mut self, operations: &mut [hal::spi::Operation<'_, u8>]) -> Result<(), Error> { + use crate::hal::spi::SpiBus; + self.cs.set_low().map_err(|_| Error::ChipSelectFault)?; + for op in operations { + match op { + spi::Operation::Read(read) => { + self.bus.read(read)?; + } + spi::Operation::Write(write) => { + self.bus.write(write)?; + } + spi::Operation::Transfer(write, read) => { + self.bus.transfer(write, read)?; } - self.cs.set_high().map_err(|_| Error::ChipSelectFault)?; - Ok(()) + spi::Operation::TransferInPlace(data) => { + self.bus.transfer_in_place(data)?; + } + spi::Operation::DelayNs(ns) => self.delay.delay_ns(*ns), } } + self.cs.set_high().map_err(|_| Error::ChipSelectFault)?; + Ok(()) + } +} - impl SpiExt for $SPIX { - fn spi(self, pins: PINS, mode: Mode, freq: Hertz, rcc: &mut Rcc) -> SpiBus<$SPIX, PINS> - where - PINS: Pins<$SPIX>, - { - SpiBus::$spiX(self, pins, mode, freq, rcc) - } - } +impl SpiExt for SPI { + fn spi(self, pins: PINS, mode: Mode, freq: Hertz, rcc: &mut Rcc) -> SpiBus + where + PINS: Pins, + { + SpiBus::new(self, pins, mode, freq, rcc) + } +} - impl SpiBus<$SPIX, PINS> { - fn receive_byte(&mut self) -> nb::Result { - let sr = self.spi.sr().read(); - Err(if sr.ovr().bit_is_set() { - nb::Error::Other(Error::Overrun) - } else if sr.modf().bit_is_set() { - nb::Error::Other(Error::ModeFault) - } else if sr.crcerr().bit_is_set() { - nb::Error::Other(Error::Crc) - } else if sr.rxne().bit_is_set() { - return Ok(self.spi.dr8().read().bits() as u8); - } else { - nb::Error::WouldBlock - }) - } +impl SpiBus { + fn receive_byte(&mut self) -> nb::Result { + let sr = self.spi.sr().read(); + + Err(if sr.ovr().bit_is_set() { + nb::Error::Other(Error::Overrun) + } else if sr.modf().bit_is_set() { + nb::Error::Other(Error::ModeFault) + } else if sr.crcerr().bit_is_set() { + nb::Error::Other(Error::Crc) + } else if sr.rxne().bit_is_set() { + // NOTE(read_volatile) read only 1 byte (the svd2rust API only allows + // reading a half-word) + return Ok(unsafe { ptr::read_volatile(&self.spi.dr() as *const _ as *const u8) }); + } else { + nb::Error::WouldBlock + }) + } - fn send_byte(&mut self, byte: u8) -> nb::Result<(), Error> { - let sr = self.spi.sr().read(); - Err(if sr.ovr().bit_is_set() { - nb::Error::Other(Error::Overrun) - } else if sr.modf().bit_is_set() { - nb::Error::Other(Error::ModeFault) - } else if sr.crcerr().bit_is_set() { - nb::Error::Other(Error::Crc) - } else if sr.txe().bit_is_set() { - self.spi.dr8().write(|w| unsafe { w.dr().bits(byte as _) }); - return Ok(()); - } else { - nb::Error::WouldBlock - }) - } - } + fn send_byte(&mut self, byte: u8) -> nb::Result<(), Error> { + let sr = self.spi.sr().read(); + Err(if sr.ovr().bit_is_set() { + nb::Error::Other(Error::Overrun) + } else if sr.modf().bit_is_set() { + nb::Error::Other(Error::ModeFault) + } else if sr.crcerr().bit_is_set() { + nb::Error::Other(Error::Crc) + } else if sr.txe().bit_is_set() { + self.spi.dr().write(|w| w.dr().set(byte.into())); + return Ok(()); + } else { + nb::Error::WouldBlock + }) + } +} + +impl ErrorType for SpiBus { + type Error = Error; +} - impl ErrorType for SpiBus<$SPIX, PINS> { - type Error = Error; +impl spi::SpiBus for SpiBus { + fn read(&mut self, bytes: &mut [u8]) -> Result<(), Self::Error> { + for byte in bytes.iter_mut() { + block!(self.send_byte(0))?; + *byte = block!(self.receive_byte())?; } + Ok(()) + } - impl spi::SpiBus for SpiBus<$SPIX, PINS> { - fn read(&mut self, bytes: &mut [u8]) -> Result<(), Self::Error> { - for byte in bytes.iter_mut() { - block!(self.send_byte(0))?; - *byte = block!(self.receive_byte())?; - } - Ok(()) - } + fn write(&mut self, bytes: &[u8]) -> Result<(), Self::Error> { + for byte in bytes.iter() { + block!(self.send_byte(*byte))?; + block!(self.receive_byte())?; + } + Ok(()) + } - fn write(&mut self, bytes: &[u8]) -> Result<(), Self::Error> { - for byte in bytes.iter() { - block!(self.send_byte(*byte))?; - block!(self.receive_byte())?; + fn transfer(&mut self, read: &mut [u8], write: &[u8]) -> Result<(), Self::Error> { + let mut iter_r = read.iter_mut(); + let mut iter_w = write.iter().cloned(); + loop { + match (iter_r.next(), iter_w.next()) { + (Some(r), Some(w)) => { + block!(self.send_byte(w))?; + *r = block!(self.receive_byte())?; } - Ok(()) - } - - fn transfer(&mut self, read: &mut [u8], write: &[u8]) -> Result<(), Self::Error> { - let mut iter_r = read.iter_mut(); - let mut iter_w = write.iter().cloned(); - loop { - match (iter_r.next(), iter_w.next()) { - (Some(r), Some(w)) => { - block!(self.send_byte(w))?; - *r = block!(self.receive_byte())?; - } - (Some(r), None) => { - block!(self.send_byte(0))?; - *r = block!(self.receive_byte())?; - } - (None, Some(w)) => { - block!(self.send_byte(w))?; - let _ = block!(self.receive_byte())?; - } - (None, None) => return Ok(()), - } + (Some(r), None) => { + block!(self.send_byte(0))?; + *r = block!(self.receive_byte())?; } - } - - fn transfer_in_place(&mut self, bytes: &mut [u8]) -> Result<(), Self::Error> { - for byte in bytes.iter_mut() { - block!(self.send_byte(*byte))?; - *byte = block!(self.receive_byte())?; + (None, Some(w)) => { + block!(self.send_byte(w))?; + let _ = block!(self.receive_byte())?; } - Ok(()) + (None, None) => return Ok(()), } + } + } - fn flush(&mut self) -> Result<(), Self::Error> { - Ok(()) - } + fn transfer_in_place(&mut self, bytes: &mut [u8]) -> Result<(), Self::Error> { + for byte in bytes.iter_mut() { + block!(self.send_byte(*byte))?; + *byte = block!(self.receive_byte())?; } + Ok(()) + } + + fn flush(&mut self) -> Result<(), Self::Error> { + Ok(()) } } spi!( - SPI1, - spi1, + pac::SPI1, sck: [ (PA1, AltFunction::AF0), (PA5, AltFunction::AF0), @@ -416,8 +429,7 @@ spi!( ); spi!( - SPI2, - spi2, + pac::SPI2, sck: [ (PA0, AltFunction::AF0), (PB8, AltFunction::AF1),