diff options
| author | Thales <[email protected]> | 2021-07-17 17:21:50 -0300 |
|---|---|---|
| committer | GitHub <[email protected]> | 2021-07-17 17:21:50 -0300 |
| commit | f4b8709bac0b6f25d0380b28358cf2fa3a8f8ee2 (patch) | |
| tree | d989d3a8e8716ab07e4029dd535e5411468a0271 | |
| parent | 59953b5b5e4935747a7f5c9699702d29ca248a2e (diff) | |
| parent | e06628cdfb3beba766c93b1ab09c237115c77d9c (diff) | |
Merge pull request #281 from thalesfragoso/i2c-256
i2c-v2: Support transfers with more than 255 bytes
| -rw-r--r-- | embassy-stm32/src/i2c/mod.rs | 2 | ||||
| -rw-r--r-- | embassy-stm32/src/i2c/v2.rs | 255 |
2 files changed, 169 insertions, 88 deletions
diff --git a/embassy-stm32/src/i2c/mod.rs b/embassy-stm32/src/i2c/mod.rs index d2da8c310..daf7e31e8 100644 --- a/embassy-stm32/src/i2c/mod.rs +++ b/embassy-stm32/src/i2c/mod.rs | |||
| @@ -6,6 +6,7 @@ mod _version; | |||
| 6 | use crate::peripherals; | 6 | use crate::peripherals; |
| 7 | pub use _version::*; | 7 | pub use _version::*; |
| 8 | 8 | ||
| 9 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 9 | pub enum Error { | 10 | pub enum Error { |
| 10 | Bus, | 11 | Bus, |
| 11 | Arbitration, | 12 | Arbitration, |
| @@ -13,6 +14,7 @@ pub enum Error { | |||
| 13 | Timeout, | 14 | Timeout, |
| 14 | Crc, | 15 | Crc, |
| 15 | Overrun, | 16 | Overrun, |
| 17 | ZeroLengthTransfer, | ||
| 16 | } | 18 | } |
| 17 | 19 | ||
| 18 | pub(crate) mod sealed { | 20 | pub(crate) mod sealed { |
diff --git a/embassy-stm32/src/i2c/v2.rs b/embassy-stm32/src/i2c/v2.rs index 2f70d4263..3179211ec 100644 --- a/embassy-stm32/src/i2c/v2.rs +++ b/embassy-stm32/src/i2c/v2.rs | |||
| @@ -81,30 +81,40 @@ impl<'d, T: Instance> I2c<'d, T> { | |||
| 81 | } | 81 | } |
| 82 | } | 82 | } |
| 83 | 83 | ||
| 84 | fn master_read(&mut self, address: u8, length: usize, stop: Stop) { | 84 | fn master_read(&mut self, address: u8, length: usize, stop: Stop, reload: bool, restart: bool) { |
| 85 | assert!(length < 256 && length > 0); | 85 | assert!(length < 256 && length > 0); |
| 86 | 86 | ||
| 87 | // Wait for any previous address sequence to end | 87 | if !restart { |
| 88 | // automatically. This could be up to 50% of a bus | 88 | // Wait for any previous address sequence to end |
| 89 | // cycle (ie. up to 0.5/freq) | 89 | // automatically. This could be up to 50% of a bus |
| 90 | while unsafe { T::regs().cr2().read().start() == i2c::vals::Start::START } {} | 90 | // cycle (ie. up to 0.5/freq) |
| 91 | while unsafe { T::regs().cr2().read().start() == i2c::vals::Start::START } {} | ||
| 92 | } | ||
| 91 | 93 | ||
| 92 | // Set START and prepare to receive bytes into | 94 | // Set START and prepare to receive bytes into |
| 93 | // `buffer`. The START bit can be set even if the bus | 95 | // `buffer`. The START bit can be set even if the bus |
| 94 | // is BUSY or I2C is in slave mode. | 96 | // is BUSY or I2C is in slave mode. |
| 95 | 97 | ||
| 98 | let reload = if reload { | ||
| 99 | i2c::vals::Reload::NOTCOMPLETED | ||
| 100 | } else { | ||
| 101 | i2c::vals::Reload::COMPLETED | ||
| 102 | }; | ||
| 103 | |||
| 96 | unsafe { | 104 | unsafe { |
| 97 | T::regs().cr2().modify(|w| { | 105 | T::regs().cr2().modify(|w| { |
| 98 | w.set_sadd((address << 1 | 0) as u16); | 106 | w.set_sadd((address << 1 | 0) as u16); |
| 107 | w.set_add10(i2c::vals::Add::BIT7); | ||
| 99 | w.set_rd_wrn(i2c::vals::RdWrn::READ); | 108 | w.set_rd_wrn(i2c::vals::RdWrn::READ); |
| 100 | w.set_nbytes(length as u8); | 109 | w.set_nbytes(length as u8); |
| 101 | w.set_start(i2c::vals::Start::START); | 110 | w.set_start(i2c::vals::Start::START); |
| 102 | w.set_autoend(stop.autoend()); | 111 | w.set_autoend(stop.autoend()); |
| 112 | w.set_reload(reload); | ||
| 103 | }); | 113 | }); |
| 104 | } | 114 | } |
| 105 | } | 115 | } |
| 106 | 116 | ||
| 107 | fn master_write(&mut self, address: u8, length: usize, stop: Stop) { | 117 | fn master_write(&mut self, address: u8, length: usize, stop: Stop, reload: bool) { |
| 108 | assert!(length < 256 && length > 0); | 118 | assert!(length < 256 && length > 0); |
| 109 | 119 | ||
| 110 | // Wait for any previous address sequence to end | 120 | // Wait for any previous address sequence to end |
| @@ -112,6 +122,12 @@ impl<'d, T: Instance> I2c<'d, T> { | |||
| 112 | // cycle (ie. up to 0.5/freq) | 122 | // cycle (ie. up to 0.5/freq) |
| 113 | while unsafe { T::regs().cr2().read().start() == i2c::vals::Start::START } {} | 123 | while unsafe { T::regs().cr2().read().start() == i2c::vals::Start::START } {} |
| 114 | 124 | ||
| 125 | let reload = if reload { | ||
| 126 | i2c::vals::Reload::NOTCOMPLETED | ||
| 127 | } else { | ||
| 128 | i2c::vals::Reload::COMPLETED | ||
| 129 | }; | ||
| 130 | |||
| 115 | // Set START and prepare to send `bytes`. The | 131 | // Set START and prepare to send `bytes`. The |
| 116 | // START bit can be set even if the bus is BUSY or | 132 | // START bit can be set even if the bus is BUSY or |
| 117 | // I2C is in slave mode. | 133 | // I2C is in slave mode. |
| @@ -123,21 +139,26 @@ impl<'d, T: Instance> I2c<'d, T> { | |||
| 123 | w.set_nbytes(length as u8); | 139 | w.set_nbytes(length as u8); |
| 124 | w.set_start(i2c::vals::Start::START); | 140 | w.set_start(i2c::vals::Start::START); |
| 125 | w.set_autoend(stop.autoend()); | 141 | w.set_autoend(stop.autoend()); |
| 142 | w.set_reload(reload); | ||
| 126 | }); | 143 | }); |
| 127 | } | 144 | } |
| 128 | } | 145 | } |
| 129 | 146 | ||
| 130 | fn master_re_start(&mut self, address: u8, length: usize, stop: Stop) { | 147 | fn master_continue(&mut self, length: usize, reload: bool) { |
| 131 | assert!(length < 256 && length > 0); | 148 | assert!(length < 256 && length > 0); |
| 132 | 149 | ||
| 150 | while unsafe { !T::regs().isr().read().tcr() } {} | ||
| 151 | |||
| 152 | let reload = if reload { | ||
| 153 | i2c::vals::Reload::NOTCOMPLETED | ||
| 154 | } else { | ||
| 155 | i2c::vals::Reload::COMPLETED | ||
| 156 | }; | ||
| 157 | |||
| 133 | unsafe { | 158 | unsafe { |
| 134 | T::regs().cr2().modify(|w| { | 159 | T::regs().cr2().modify(|w| { |
| 135 | w.set_sadd((address << 1 | 1) as u16); | ||
| 136 | w.set_add10(i2c::vals::Add::BIT7); | ||
| 137 | w.set_rd_wrn(i2c::vals::RdWrn::READ); | ||
| 138 | w.set_nbytes(length as u8); | 160 | w.set_nbytes(length as u8); |
| 139 | w.set_start(i2c::vals::Start::START); | 161 | w.set_reload(reload); |
| 140 | w.set_autoend(stop.autoend()); | ||
| 141 | }); | 162 | }); |
| 142 | } | 163 | } |
| 143 | } | 164 | } |
| @@ -224,117 +245,175 @@ impl<'d, T: Instance> I2c<'d, T> { | |||
| 224 | } | 245 | } |
| 225 | } | 246 | } |
| 226 | } | 247 | } |
| 227 | } | ||
| 228 | |||
| 229 | impl<'d, T: Instance> Read for I2c<'d, T> { | ||
| 230 | type Error = Error; | ||
| 231 | 248 | ||
| 232 | fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Self::Error> { | 249 | fn read(&mut self, address: u8, buffer: &mut [u8], restart: bool) -> Result<(), Error> { |
| 233 | assert!(buffer.len() < 256 && buffer.len() > 0); | 250 | let completed_chunks = buffer.len() / 255; |
| 251 | let total_chunks = if completed_chunks * 255 == buffer.len() { | ||
| 252 | completed_chunks | ||
| 253 | } else { | ||
| 254 | completed_chunks + 1 | ||
| 255 | }; | ||
| 256 | let last_chunk_idx = total_chunks.saturating_sub(1); | ||
| 257 | |||
| 258 | self.master_read( | ||
| 259 | address, | ||
| 260 | buffer.len().min(255), | ||
| 261 | Stop::Automatic, | ||
| 262 | last_chunk_idx != 0, | ||
| 263 | restart, | ||
| 264 | ); | ||
| 234 | 265 | ||
| 235 | self.master_read(address, buffer.len(), Stop::Automatic); | 266 | for (number, chunk) in buffer.chunks_mut(255).enumerate() { |
| 267 | if number != 0 { | ||
| 268 | self.master_continue(chunk.len(), number != last_chunk_idx); | ||
| 269 | } | ||
| 236 | 270 | ||
| 237 | for byte in buffer { | 271 | for byte in chunk { |
| 238 | // Wait until we have received something | 272 | // Wait until we have received something |
| 239 | self.wait_rxne()?; | 273 | self.wait_rxne()?; |
| 240 | 274 | ||
| 241 | //*byte = self.i2c.rxdr.read().rxdata().bits(); | 275 | unsafe { |
| 242 | unsafe { | 276 | *byte = T::regs().rxdr().read().rxdata(); |
| 243 | *byte = T::regs().rxdr().read().rxdata(); | 277 | } |
| 244 | } | 278 | } |
| 245 | } | 279 | } |
| 246 | |||
| 247 | // automatic STOP | ||
| 248 | Ok(()) | 280 | Ok(()) |
| 249 | } | 281 | } |
| 250 | } | ||
| 251 | |||
| 252 | impl<'d, T: Instance> Write for I2c<'d, T> { | ||
| 253 | type Error = Error; | ||
| 254 | 282 | ||
| 255 | fn write(&mut self, address: u8, bytes: &[u8]) -> Result<(), Self::Error> { | 283 | fn write(&mut self, address: u8, bytes: &[u8], send_stop: bool) -> Result<(), Error> { |
| 256 | // TODO support transfers of more than 255 bytes | 284 | let completed_chunks = bytes.len() / 255; |
| 257 | assert!(bytes.len() < 256 && bytes.len() > 0); | 285 | let total_chunks = if completed_chunks * 255 == bytes.len() { |
| 286 | completed_chunks | ||
| 287 | } else { | ||
| 288 | completed_chunks + 1 | ||
| 289 | }; | ||
| 290 | let last_chunk_idx = total_chunks.saturating_sub(1); | ||
| 258 | 291 | ||
| 259 | // I2C start | 292 | // I2C start |
| 260 | // | 293 | // |
| 261 | // ST SAD+W | 294 | // ST SAD+W |
| 262 | self.master_write(address, bytes.len(), Stop::Software); | 295 | self.master_write( |
| 296 | address, | ||
| 297 | bytes.len().min(255), | ||
| 298 | Stop::Software, | ||
| 299 | last_chunk_idx != 0, | ||
| 300 | ); | ||
| 301 | |||
| 302 | for (number, chunk) in bytes.chunks(255).enumerate() { | ||
| 303 | if number != 0 { | ||
| 304 | self.master_continue(chunk.len(), number != last_chunk_idx); | ||
| 305 | } | ||
| 263 | 306 | ||
| 264 | for byte in bytes { | 307 | for byte in chunk { |
| 265 | // Wait until we are allowed to send data | 308 | // Wait until we are allowed to send data |
| 266 | // (START has been ACKed or last byte when | 309 | // (START has been ACKed or last byte when |
| 267 | // through) | 310 | // through) |
| 268 | self.wait_txe()?; | 311 | self.wait_txe()?; |
| 269 | 312 | ||
| 270 | // Put byte on the wire | 313 | unsafe { |
| 271 | //self.i2c.txdr.write(|w| w.txdata().bits(*byte)); | 314 | T::regs().txdr().write(|w| w.set_txdata(*byte)); |
| 272 | unsafe { | 315 | } |
| 273 | T::regs().txdr().write(|w| w.set_txdata(*byte)); | ||
| 274 | } | 316 | } |
| 275 | } | 317 | } |
| 276 | |||
| 277 | // Wait until the write finishes | 318 | // Wait until the write finishes |
| 278 | self.wait_tc()?; | 319 | self.wait_tc()?; |
| 279 | 320 | ||
| 280 | // Stop | 321 | if send_stop { |
| 281 | self.master_stop(); | 322 | self.master_stop(); |
| 282 | 323 | } | |
| 283 | Ok(()) | 324 | Ok(()) |
| 284 | } | 325 | } |
| 285 | } | ||
| 286 | 326 | ||
| 287 | impl<'d, T: Instance> WriteRead for I2c<'d, T> { | 327 | pub fn write_vectored(&mut self, address: u8, bytes: &[&[u8]]) -> Result<(), Error> { |
| 288 | type Error = Error; | 328 | if bytes.is_empty() { |
| 329 | return Err(Error::ZeroLengthTransfer); | ||
| 330 | } | ||
| 331 | let first_length = bytes[0].len(); | ||
| 332 | let last_slice_index = bytes.len() - 1; | ||
| 333 | |||
| 334 | self.master_write( | ||
| 335 | address, | ||
| 336 | first_length.min(255), | ||
| 337 | Stop::Software, | ||
| 338 | (first_length > 255) || (last_slice_index != 0), | ||
| 339 | ); | ||
| 289 | 340 | ||
| 290 | fn write_read( | 341 | for (idx, slice) in bytes.iter().enumerate() { |
| 291 | &mut self, | 342 | let slice_len = slice.len(); |
| 292 | address: u8, | 343 | let completed_chunks = slice_len / 255; |
| 293 | bytes: &[u8], | 344 | let total_chunks = if completed_chunks * 255 == slice_len { |
| 294 | buffer: &mut [u8], | 345 | completed_chunks |
| 295 | ) -> Result<(), Self::Error> { | 346 | } else { |
| 296 | // TODO support transfers of more than 255 bytes | 347 | completed_chunks + 1 |
| 297 | assert!(bytes.len() < 256 && bytes.len() > 0); | 348 | }; |
| 298 | assert!(buffer.len() < 256 && buffer.len() > 0); | 349 | let last_chunk_idx = total_chunks.saturating_sub(1); |
| 299 | 350 | ||
| 300 | // I2C start | 351 | if idx != 0 { |
| 301 | // | 352 | self.master_continue( |
| 302 | // ST SAD+W | 353 | slice_len.min(255), |
| 303 | self.master_write(address, bytes.len(), Stop::Software); | 354 | (idx != last_slice_index) || (slice_len > 255), |
| 355 | ); | ||
| 356 | } | ||
| 304 | 357 | ||
| 305 | for byte in bytes { | 358 | for (number, chunk) in slice.chunks(255).enumerate() { |
| 306 | // Wait until we are allowed to send data | 359 | if number != 0 { |
| 307 | // (START has been ACKed or last byte went through) | 360 | self.master_continue( |
| 308 | self.wait_txe()?; | 361 | chunk.len(), |
| 362 | (number != last_chunk_idx) || (idx != last_slice_index), | ||
| 363 | ); | ||
| 364 | } | ||
| 309 | 365 | ||
| 310 | // Put byte on the wire | 366 | for byte in chunk { |
| 311 | //self.i2c.txdr.write(|w| w.txdata().bits(*byte)); | 367 | // Wait until we are allowed to send data |
| 312 | unsafe { | 368 | // (START has been ACKed or last byte when |
| 313 | T::regs().txdr().write(|w| w.set_txdata(*byte)); | 369 | // through) |
| 370 | self.wait_txe()?; | ||
| 371 | |||
| 372 | // Put byte on the wire | ||
| 373 | //self.i2c.txdr.write(|w| w.txdata().bits(*byte)); | ||
| 374 | unsafe { | ||
| 375 | T::regs().txdr().write(|w| w.set_txdata(*byte)); | ||
| 376 | } | ||
| 377 | } | ||
| 314 | } | 378 | } |
| 315 | } | 379 | } |
| 316 | 380 | // Wait until the write finishes | |
| 317 | // Wait until the write finishes before beginning to read. | ||
| 318 | self.wait_tc()?; | 381 | self.wait_tc()?; |
| 382 | self.master_stop(); | ||
| 319 | 383 | ||
| 320 | // I2C re-start | 384 | Ok(()) |
| 321 | // | 385 | } |
| 322 | // SR SAD+R | 386 | } |
| 323 | self.master_re_start(address, buffer.len(), Stop::Automatic); | ||
| 324 | 387 | ||
| 325 | for byte in buffer { | 388 | impl<'d, T: Instance> Read for I2c<'d, T> { |
| 326 | // Wait until we have received something | 389 | type Error = Error; |
| 327 | self.wait_rxne()?; | ||
| 328 | 390 | ||
| 329 | //*byte = self.i2c.rxdr.read().rxdata().bits(); | 391 | fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Self::Error> { |
| 330 | unsafe { | 392 | self.read(address, buffer, false) |
| 331 | *byte = T::regs().rxdr().read().rxdata(); | 393 | // Automatic Stop |
| 332 | } | 394 | } |
| 333 | } | 395 | } |
| 334 | 396 | ||
| 335 | // automatic STOP | 397 | impl<'d, T: Instance> Write for I2c<'d, T> { |
| 398 | type Error = Error; | ||
| 336 | 399 | ||
| 337 | Ok(()) | 400 | fn write(&mut self, address: u8, bytes: &[u8]) -> Result<(), Self::Error> { |
| 401 | self.write(address, bytes, true) | ||
| 402 | } | ||
| 403 | } | ||
| 404 | |||
| 405 | impl<'d, T: Instance> WriteRead for I2c<'d, T> { | ||
| 406 | type Error = Error; | ||
| 407 | |||
| 408 | fn write_read( | ||
| 409 | &mut self, | ||
| 410 | address: u8, | ||
| 411 | bytes: &[u8], | ||
| 412 | buffer: &mut [u8], | ||
| 413 | ) -> Result<(), Self::Error> { | ||
| 414 | self.write(address, bytes, false)?; | ||
| 415 | self.read(address, buffer, true) | ||
| 416 | // Automatic Stop | ||
| 338 | } | 417 | } |
| 339 | } | 418 | } |
| 340 | 419 | ||
