diff options
| author | HybridChild <[email protected]> | 2025-11-12 19:31:21 +0100 |
|---|---|---|
| committer | HybridChild <[email protected]> | 2025-11-12 19:57:56 +0100 |
| commit | 74b5f14ede9a6b4349932bff41dac077afc47fa2 (patch) | |
| tree | 991b5fe31e49f555b661643df0556442c26b8fd6 | |
| parent | aa5c0c02425104fceea9e5dc773e3f5c346e9656 (diff) | |
stm32/i2c_v2: Refactor transaction implementation
| -rw-r--r-- | embassy-stm32/src/i2c/v2.rs | 87 |
1 files changed, 33 insertions, 54 deletions
diff --git a/embassy-stm32/src/i2c/v2.rs b/embassy-stm32/src/i2c/v2.rs index 061f4ff3a..3c43887c0 100644 --- a/embassy-stm32/src/i2c/v2.rs +++ b/embassy-stm32/src/i2c/v2.rs | |||
| @@ -98,6 +98,27 @@ pub(crate) unsafe fn on_interrupt<T: Instance>() { | |||
| 98 | } | 98 | } |
| 99 | 99 | ||
| 100 | impl<'d, M: Mode, IM: MasterMode> I2c<'d, M, IM> { | 100 | impl<'d, M: Mode, IM: MasterMode> I2c<'d, M, IM> { |
| 101 | #[inline] | ||
| 102 | fn to_reload(reload: bool) -> i2c::vals::Reload { | ||
| 103 | if reload { | ||
| 104 | i2c::vals::Reload::NOT_COMPLETED | ||
| 105 | } else { | ||
| 106 | i2c::vals::Reload::COMPLETED | ||
| 107 | } | ||
| 108 | } | ||
| 109 | |||
| 110 | /// Calculate total bytes in a group of operations | ||
| 111 | #[inline] | ||
| 112 | fn total_operation_bytes(operations: &[Operation<'_>]) -> usize { | ||
| 113 | operations | ||
| 114 | .iter() | ||
| 115 | .map(|op| match op { | ||
| 116 | Operation::Write(buf) => buf.len(), | ||
| 117 | Operation::Read(buf) => buf.len(), | ||
| 118 | }) | ||
| 119 | .sum() | ||
| 120 | } | ||
| 121 | |||
| 101 | pub(crate) fn init(&mut self, config: Config) { | 122 | pub(crate) fn init(&mut self, config: Config) { |
| 102 | self.info.regs.cr1().modify(|reg| { | 123 | self.info.regs.cr1().modify(|reg| { |
| 103 | reg.set_pe(false); | 124 | reg.set_pe(false); |
| @@ -147,12 +168,6 @@ impl<'d, M: Mode, IM: MasterMode> I2c<'d, M, IM> { | |||
| 147 | // `buffer`. The START bit can be set even if the bus | 168 | // `buffer`. The START bit can be set even if the bus |
| 148 | // is BUSY or I2C is in slave mode. | 169 | // is BUSY or I2C is in slave mode. |
| 149 | 170 | ||
| 150 | let reload = if reload { | ||
| 151 | i2c::vals::Reload::NOT_COMPLETED | ||
| 152 | } else { | ||
| 153 | i2c::vals::Reload::COMPLETED | ||
| 154 | }; | ||
| 155 | |||
| 156 | info.regs.cr2().modify(|w| { | 171 | info.regs.cr2().modify(|w| { |
| 157 | w.set_sadd(address.addr() << 1); | 172 | w.set_sadd(address.addr() << 1); |
| 158 | w.set_add10(address.add_mode()); | 173 | w.set_add10(address.add_mode()); |
| @@ -160,7 +175,7 @@ impl<'d, M: Mode, IM: MasterMode> I2c<'d, M, IM> { | |||
| 160 | w.set_nbytes(length as u8); | 175 | w.set_nbytes(length as u8); |
| 161 | w.set_start(true); | 176 | w.set_start(true); |
| 162 | w.set_autoend(stop.autoend()); | 177 | w.set_autoend(stop.autoend()); |
| 163 | w.set_reload(reload); | 178 | w.set_reload(Self::to_reload(reload)); |
| 164 | }); | 179 | }); |
| 165 | 180 | ||
| 166 | Ok(()) | 181 | Ok(()) |
| @@ -191,12 +206,6 @@ impl<'d, M: Mode, IM: MasterMode> I2c<'d, M, IM> { | |||
| 191 | } | 206 | } |
| 192 | } | 207 | } |
| 193 | 208 | ||
| 194 | let reload = if reload { | ||
| 195 | i2c::vals::Reload::NOT_COMPLETED | ||
| 196 | } else { | ||
| 197 | i2c::vals::Reload::COMPLETED | ||
| 198 | }; | ||
| 199 | |||
| 200 | // Set START and prepare to send `bytes`. The | 209 | // Set START and prepare to send `bytes`. The |
| 201 | // START bit can be set even if the bus is BUSY or | 210 | // START bit can be set even if the bus is BUSY or |
| 202 | // I2C is in slave mode. | 211 | // I2C is in slave mode. |
| @@ -207,7 +216,7 @@ impl<'d, M: Mode, IM: MasterMode> I2c<'d, M, IM> { | |||
| 207 | w.set_nbytes(length as u8); | 216 | w.set_nbytes(length as u8); |
| 208 | w.set_start(true); | 217 | w.set_start(true); |
| 209 | w.set_autoend(stop.autoend()); | 218 | w.set_autoend(stop.autoend()); |
| 210 | w.set_reload(reload); | 219 | w.set_reload(Self::to_reload(reload)); |
| 211 | }); | 220 | }); |
| 212 | 221 | ||
| 213 | Ok(()) | 222 | Ok(()) |
| @@ -220,15 +229,9 @@ impl<'d, M: Mode, IM: MasterMode> I2c<'d, M, IM> { | |||
| 220 | timeout.check()?; | 229 | timeout.check()?; |
| 221 | } | 230 | } |
| 222 | 231 | ||
| 223 | let will_reload = if will_reload { | ||
| 224 | i2c::vals::Reload::NOT_COMPLETED | ||
| 225 | } else { | ||
| 226 | i2c::vals::Reload::COMPLETED | ||
| 227 | }; | ||
| 228 | |||
| 229 | info.regs.cr2().modify(|w| { | 232 | info.regs.cr2().modify(|w| { |
| 230 | w.set_nbytes(length as u8); | 233 | w.set_nbytes(length as u8); |
| 231 | w.set_reload(will_reload); | 234 | w.set_reload(Self::to_reload(will_reload)); |
| 232 | w.set_autoend(stop.autoend()); | 235 | w.set_autoend(stop.autoend()); |
| 233 | }); | 236 | }); |
| 234 | 237 | ||
| @@ -400,7 +403,7 @@ impl<'d, M: Mode, IM: MasterMode> I2c<'d, M, IM> { | |||
| 400 | address, | 403 | address, |
| 401 | read.len().min(255), | 404 | read.len().min(255), |
| 402 | Stop::Automatic, | 405 | Stop::Automatic, |
| 403 | last_chunk_idx != 0, | 406 | last_chunk_idx != 0, // reload |
| 404 | restart, | 407 | restart, |
| 405 | timeout, | 408 | timeout, |
| 406 | )?; | 409 | )?; |
| @@ -569,13 +572,7 @@ impl<'d, M: Mode, IM: MasterMode> I2c<'d, M, IM> { | |||
| 569 | timeout: Timeout, | 572 | timeout: Timeout, |
| 570 | ) -> Result<(), Error> { | 573 | ) -> Result<(), Error> { |
| 571 | // Calculate total bytes across all operations in this group | 574 | // Calculate total bytes across all operations in this group |
| 572 | let total_bytes: usize = operations | 575 | let total_bytes = Self::total_operation_bytes(operations); |
| 573 | .iter() | ||
| 574 | .map(|op| match op { | ||
| 575 | Operation::Write(buf) => buf.len(), | ||
| 576 | _ => 0, | ||
| 577 | }) | ||
| 578 | .sum(); | ||
| 579 | 576 | ||
| 580 | if total_bytes == 0 { | 577 | if total_bytes == 0 { |
| 581 | // Handle empty write group - just send address | 578 | // Handle empty write group - just send address |
| @@ -641,13 +638,7 @@ impl<'d, M: Mode, IM: MasterMode> I2c<'d, M, IM> { | |||
| 641 | timeout: Timeout, | 638 | timeout: Timeout, |
| 642 | ) -> Result<(), Error> { | 639 | ) -> Result<(), Error> { |
| 643 | // Calculate total bytes across all operations in this group | 640 | // Calculate total bytes across all operations in this group |
| 644 | let total_bytes: usize = operations | 641 | let total_bytes = Self::total_operation_bytes(operations); |
| 645 | .iter() | ||
| 646 | .map(|op| match op { | ||
| 647 | Operation::Read(buf) => buf.len(), | ||
| 648 | _ => 0, | ||
| 649 | }) | ||
| 650 | .sum(); | ||
| 651 | 642 | ||
| 652 | if total_bytes == 0 { | 643 | if total_bytes == 0 { |
| 653 | // Handle empty read group | 644 | // Handle empty read group |
| @@ -657,7 +648,7 @@ impl<'d, M: Mode, IM: MasterMode> I2c<'d, M, IM> { | |||
| 657 | address, | 648 | address, |
| 658 | 0, | 649 | 0, |
| 659 | if is_last_group { Stop::Automatic } else { Stop::Software }, | 650 | if is_last_group { Stop::Automatic } else { Stop::Software }, |
| 660 | false, | 651 | false, // reload |
| 661 | !is_first_group, | 652 | !is_first_group, |
| 662 | timeout, | 653 | timeout, |
| 663 | )?; | 654 | )?; |
| @@ -1000,7 +991,7 @@ impl<'d, IM: MasterMode> I2c<'d, Async, IM> { | |||
| 1000 | address, | 991 | address, |
| 1001 | total_len.min(255), | 992 | total_len.min(255), |
| 1002 | Stop::Automatic, | 993 | Stop::Automatic, |
| 1003 | total_len > 255, | 994 | total_len > 255, // reload |
| 1004 | restart, | 995 | restart, |
| 1005 | timeout, | 996 | timeout, |
| 1006 | )?; | 997 | )?; |
| @@ -1183,13 +1174,7 @@ impl<'d, IM: MasterMode> I2c<'d, Async, IM> { | |||
| 1183 | timeout: Timeout, | 1174 | timeout: Timeout, |
| 1184 | ) -> Result<(), Error> { | 1175 | ) -> Result<(), Error> { |
| 1185 | // Calculate total bytes across all operations in this group | 1176 | // Calculate total bytes across all operations in this group |
| 1186 | let total_bytes: usize = operations | 1177 | let total_bytes = Self::total_operation_bytes(operations); |
| 1187 | .iter() | ||
| 1188 | .map(|op| match op { | ||
| 1189 | Operation::Write(buf) => buf.len(), | ||
| 1190 | _ => 0, | ||
| 1191 | }) | ||
| 1192 | .sum(); | ||
| 1193 | 1178 | ||
| 1194 | if total_bytes == 0 { | 1179 | if total_bytes == 0 { |
| 1195 | // Handle empty write group using blocking call | 1180 | // Handle empty write group using blocking call |
| @@ -1249,13 +1234,7 @@ impl<'d, IM: MasterMode> I2c<'d, Async, IM> { | |||
| 1249 | timeout: Timeout, | 1234 | timeout: Timeout, |
| 1250 | ) -> Result<(), Error> { | 1235 | ) -> Result<(), Error> { |
| 1251 | // Calculate total bytes across all operations in this group | 1236 | // Calculate total bytes across all operations in this group |
| 1252 | let total_bytes: usize = operations | 1237 | let total_bytes = Self::total_operation_bytes(operations); |
| 1253 | .iter() | ||
| 1254 | .map(|op| match op { | ||
| 1255 | Operation::Read(buf) => buf.len(), | ||
| 1256 | _ => 0, | ||
| 1257 | }) | ||
| 1258 | .sum(); | ||
| 1259 | 1238 | ||
| 1260 | if total_bytes == 0 { | 1239 | if total_bytes == 0 { |
| 1261 | // Handle empty read group using blocking call | 1240 | // Handle empty read group using blocking call |
| @@ -1265,7 +1244,7 @@ impl<'d, IM: MasterMode> I2c<'d, Async, IM> { | |||
| 1265 | address, | 1244 | address, |
| 1266 | 0, | 1245 | 0, |
| 1267 | if is_last_group { Stop::Automatic } else { Stop::Software }, | 1246 | if is_last_group { Stop::Automatic } else { Stop::Software }, |
| 1268 | false, | 1247 | false, // reload |
| 1269 | !is_first_group, | 1248 | !is_first_group, |
| 1270 | timeout, | 1249 | timeout, |
| 1271 | )?; | 1250 | )?; |
| @@ -1313,7 +1292,7 @@ impl<'d, IM: MasterMode> I2c<'d, Async, IM> { | |||
| 1313 | } else { | 1292 | } else { |
| 1314 | Stop::Software | 1293 | Stop::Software |
| 1315 | }, | 1294 | }, |
| 1316 | last_chunk_idx != 0 || !is_last_read, | 1295 | last_chunk_idx != 0 || !is_last_read, // reload |
| 1317 | restart, | 1296 | restart, |
| 1318 | timeout, | 1297 | timeout, |
| 1319 | )?; | 1298 | )?; |
