diff options
| author | Thales Fragoso <[email protected]> | 2021-07-07 21:35:56 -0300 |
|---|---|---|
| committer | Thales Fragoso <[email protected]> | 2021-07-14 23:39:50 -0300 |
| commit | 8c7f8a61e327078cf68a32a5f282f301f335ffd1 (patch) | |
| tree | 359fe71a73bb28e8ac68fdc74e11e401d7abd586 | |
| parent | 8a172ac12325ddc382e5ac0ffa637120a166d057 (diff) | |
i2c-v2: Support transfers with more than 255 bytes
| -rw-r--r-- | embassy-stm32/src/i2c/v2.rs | 185 |
1 files changed, 96 insertions, 89 deletions
diff --git a/embassy-stm32/src/i2c/v2.rs b/embassy-stm32/src/i2c/v2.rs index 2f70d4263..b7aa84586 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,24 @@ 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 | let reload = if reload { | ||
| 151 | i2c::vals::Reload::NOTCOMPLETED | ||
| 152 | } else { | ||
| 153 | i2c::vals::Reload::COMPLETED | ||
| 154 | }; | ||
| 155 | |||
| 133 | unsafe { | 156 | unsafe { |
| 134 | T::regs().cr2().modify(|w| { | 157 | 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); | 158 | w.set_nbytes(length as u8); |
| 139 | w.set_start(i2c::vals::Start::START); | 159 | w.set_reload(reload); |
| 140 | w.set_autoend(stop.autoend()); | ||
| 141 | }); | 160 | }); |
| 142 | } | 161 | } |
| 143 | } | 162 | } |
| @@ -224,66 +243,93 @@ impl<'d, T: Instance> I2c<'d, T> { | |||
| 224 | } | 243 | } |
| 225 | } | 244 | } |
| 226 | } | 245 | } |
| 227 | } | ||
| 228 | 246 | ||
| 229 | impl<'d, T: Instance> Read for I2c<'d, T> { | 247 | fn read(&mut self, address: u8, buffer: &mut [u8], restart: bool) -> Result<(), Error> { |
| 230 | type Error = Error; | 248 | let last_chunk = (buffer.len() / 255).saturating_sub(1); |
| 231 | 249 | ||
| 232 | fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Self::Error> { | 250 | self.master_read( |
| 233 | assert!(buffer.len() < 256 && buffer.len() > 0); | 251 | address, |
| 252 | buffer.len().min(255), | ||
| 253 | Stop::Automatic, | ||
| 254 | last_chunk != 0, | ||
| 255 | restart, | ||
| 256 | ); | ||
| 234 | 257 | ||
| 235 | self.master_read(address, buffer.len(), Stop::Automatic); | 258 | for (number, chunk) in buffer.chunks_mut(255).enumerate() { |
| 259 | if number != 0 { | ||
| 260 | self.master_continue(chunk.len(), number != last_chunk); | ||
| 261 | } | ||
| 236 | 262 | ||
| 237 | for byte in buffer { | 263 | for byte in chunk { |
| 238 | // Wait until we have received something | 264 | // Wait until we have received something |
| 239 | self.wait_rxne()?; | 265 | self.wait_rxne()?; |
| 240 | 266 | ||
| 241 | //*byte = self.i2c.rxdr.read().rxdata().bits(); | 267 | unsafe { |
| 242 | unsafe { | 268 | *byte = T::regs().rxdr().read().rxdata(); |
| 243 | *byte = T::regs().rxdr().read().rxdata(); | 269 | } |
| 244 | } | 270 | } |
| 245 | } | 271 | } |
| 246 | |||
| 247 | // automatic STOP | ||
| 248 | Ok(()) | 272 | Ok(()) |
| 249 | } | 273 | } |
| 250 | } | ||
| 251 | 274 | ||
| 252 | impl<'d, T: Instance> Write for I2c<'d, T> { | 275 | fn write(&mut self, address: u8, bytes: &[u8], send_stop: bool) -> Result<(), Error> { |
| 253 | type Error = Error; | 276 | let last_chunk = (bytes.len() / 255).saturating_sub(1); |
| 254 | |||
| 255 | fn write(&mut self, address: u8, bytes: &[u8]) -> Result<(), Self::Error> { | ||
| 256 | // TODO support transfers of more than 255 bytes | ||
| 257 | assert!(bytes.len() < 256 && bytes.len() > 0); | ||
| 258 | 277 | ||
| 259 | // I2C start | 278 | // I2C start |
| 260 | // | 279 | // |
| 261 | // ST SAD+W | 280 | // ST SAD+W |
| 262 | self.master_write(address, bytes.len(), Stop::Software); | 281 | self.master_write( |
| 282 | address, | ||
| 283 | bytes.len().min(255), | ||
| 284 | Stop::Software, | ||
| 285 | last_chunk != 0, | ||
| 286 | ); | ||
| 263 | 287 | ||
| 264 | for byte in bytes { | 288 | for (number, chunk) in bytes.chunks(255).enumerate() { |
| 265 | // Wait until we are allowed to send data | 289 | if number != 0 { |
| 266 | // (START has been ACKed or last byte when | 290 | self.master_continue(chunk.len(), number != last_chunk); |
| 267 | // through) | 291 | } |
| 268 | self.wait_txe()?; | ||
| 269 | 292 | ||
| 270 | // Put byte on the wire | 293 | for byte in chunk { |
| 271 | //self.i2c.txdr.write(|w| w.txdata().bits(*byte)); | 294 | // Wait until we are allowed to send data |
| 272 | unsafe { | 295 | // (START has been ACKed or last byte when |
| 273 | T::regs().txdr().write(|w| w.set_txdata(*byte)); | 296 | // through) |
| 297 | self.wait_txe()?; | ||
| 298 | |||
| 299 | // Put byte on the wire | ||
| 300 | //self.i2c.txdr.write(|w| w.txdata().bits(*byte)); | ||
| 301 | unsafe { | ||
| 302 | T::regs().txdr().write(|w| w.set_txdata(*byte)); | ||
| 303 | } | ||
| 274 | } | 304 | } |
| 275 | } | 305 | } |
| 276 | |||
| 277 | // Wait until the write finishes | 306 | // Wait until the write finishes |
| 278 | self.wait_tc()?; | 307 | self.wait_tc()?; |
| 279 | 308 | ||
| 280 | // Stop | 309 | if send_stop { |
| 281 | self.master_stop(); | 310 | self.master_stop(); |
| 282 | 311 | } | |
| 283 | Ok(()) | 312 | Ok(()) |
| 284 | } | 313 | } |
| 285 | } | 314 | } |
| 286 | 315 | ||
| 316 | impl<'d, T: Instance> Read for I2c<'d, T> { | ||
| 317 | type Error = Error; | ||
| 318 | |||
| 319 | fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Self::Error> { | ||
| 320 | self.read(address, buffer, false) | ||
| 321 | // Automatic Stop | ||
| 322 | } | ||
| 323 | } | ||
| 324 | |||
| 325 | impl<'d, T: Instance> Write for I2c<'d, T> { | ||
| 326 | type Error = Error; | ||
| 327 | |||
| 328 | fn write(&mut self, address: u8, bytes: &[u8]) -> Result<(), Self::Error> { | ||
| 329 | self.write(address, bytes, true) | ||
| 330 | } | ||
| 331 | } | ||
| 332 | |||
| 287 | impl<'d, T: Instance> WriteRead for I2c<'d, T> { | 333 | impl<'d, T: Instance> WriteRead for I2c<'d, T> { |
| 288 | type Error = Error; | 334 | type Error = Error; |
| 289 | 335 | ||
| @@ -293,48 +339,9 @@ impl<'d, T: Instance> WriteRead for I2c<'d, T> { | |||
| 293 | bytes: &[u8], | 339 | bytes: &[u8], |
| 294 | buffer: &mut [u8], | 340 | buffer: &mut [u8], |
| 295 | ) -> Result<(), Self::Error> { | 341 | ) -> Result<(), Self::Error> { |
| 296 | // TODO support transfers of more than 255 bytes | 342 | self.write(address, bytes, false)?; |
| 297 | assert!(bytes.len() < 256 && bytes.len() > 0); | 343 | self.read(address, buffer, true) |
| 298 | assert!(buffer.len() < 256 && buffer.len() > 0); | 344 | // Automatic Stop |
| 299 | |||
| 300 | // I2C start | ||
| 301 | // | ||
| 302 | // ST SAD+W | ||
| 303 | self.master_write(address, bytes.len(), Stop::Software); | ||
| 304 | |||
| 305 | for byte in bytes { | ||
| 306 | // Wait until we are allowed to send data | ||
| 307 | // (START has been ACKed or last byte went through) | ||
| 308 | self.wait_txe()?; | ||
| 309 | |||
| 310 | // Put byte on the wire | ||
| 311 | //self.i2c.txdr.write(|w| w.txdata().bits(*byte)); | ||
| 312 | unsafe { | ||
| 313 | T::regs().txdr().write(|w| w.set_txdata(*byte)); | ||
| 314 | } | ||
| 315 | } | ||
| 316 | |||
| 317 | // Wait until the write finishes before beginning to read. | ||
| 318 | self.wait_tc()?; | ||
| 319 | |||
| 320 | // I2C re-start | ||
| 321 | // | ||
| 322 | // SR SAD+R | ||
| 323 | self.master_re_start(address, buffer.len(), Stop::Automatic); | ||
| 324 | |||
| 325 | for byte in buffer { | ||
| 326 | // Wait until we have received something | ||
| 327 | self.wait_rxne()?; | ||
| 328 | |||
| 329 | //*byte = self.i2c.rxdr.read().rxdata().bits(); | ||
| 330 | unsafe { | ||
| 331 | *byte = T::regs().rxdr().read().rxdata(); | ||
| 332 | } | ||
| 333 | } | ||
| 334 | |||
| 335 | // automatic STOP | ||
| 336 | |||
| 337 | Ok(()) | ||
| 338 | } | 345 | } |
| 339 | } | 346 | } |
| 340 | 347 | ||
