|
2 | 2 |
|
3 | 3 | use core::{fmt::Debug, future::Future};
|
4 | 4 |
|
5 |
| -use embedded_hal::digital::OutputPin; |
6 | 5 | use embedded_hal::spi as blocking;
|
7 | 6 | pub use embedded_hal::spi::{
|
8 | 7 | Error, ErrorKind, ErrorType, Mode, Phase, Polarity, MODE_0, MODE_1, MODE_2, MODE_3,
|
9 | 8 | };
|
| 9 | +use embedded_hal::{digital::OutputPin, spi::Operation}; |
10 | 10 |
|
11 | 11 | #[macro_export]
|
12 | 12 | /// Do an SPI transaction on a bus.
|
@@ -374,30 +374,112 @@ where
|
374 | 374 | type Error = ExclusiveDeviceError<BUS::Error, CS::Error>;
|
375 | 375 | }
|
376 | 376 |
|
377 |
| -impl<BUS, CS> blocking::SpiDevice for ExclusiveDevice<BUS, CS> |
| 377 | +impl<Word: Copy + 'static, BUS, CS> blocking::SpiDeviceRead<Word> for ExclusiveDevice<BUS, CS> |
378 | 378 | where
|
379 |
| - BUS: blocking::SpiBusFlush, |
| 379 | + BUS: blocking::SpiBusRead<Word>, |
380 | 380 | CS: OutputPin,
|
381 | 381 | {
|
382 |
| - type Bus = BUS; |
| 382 | + fn read_transaction(&mut self, operations: &mut [&mut [Word]]) -> Result<(), Self::Error> { |
| 383 | + self.cs.set_low().map_err(ExclusiveDeviceError::Cs)?; |
| 384 | + |
| 385 | + let mut op_res = Ok(()); |
| 386 | + |
| 387 | + for buf in operations { |
| 388 | + if let Err(e) = self.bus.read(buf) { |
| 389 | + op_res = Err(e); |
| 390 | + break; |
| 391 | + } |
| 392 | + } |
| 393 | + |
| 394 | + // On failure, it's important to still flush and deassert CS. |
| 395 | + let flush_res = self.bus.flush(); |
| 396 | + let cs_res = self.cs.set_high(); |
| 397 | + |
| 398 | + op_res.map_err(ExclusiveDeviceError::Spi)?; |
| 399 | + flush_res.map_err(ExclusiveDeviceError::Spi)?; |
| 400 | + cs_res.map_err(ExclusiveDeviceError::Cs)?; |
| 401 | + |
| 402 | + Ok(()) |
| 403 | + } |
| 404 | +} |
| 405 | + |
| 406 | +impl<Word: Copy + 'static, BUS, CS> blocking::SpiDeviceWrite<Word> for ExclusiveDevice<BUS, CS> |
| 407 | +where |
| 408 | + BUS: blocking::SpiBusWrite<Word>, |
| 409 | + CS: OutputPin, |
| 410 | +{ |
| 411 | + fn write_transaction(&mut self, operations: &[&[Word]]) -> Result<(), Self::Error> { |
| 412 | + self.cs.set_low().map_err(ExclusiveDeviceError::Cs)?; |
383 | 413 |
|
384 |
| - fn transaction<R>( |
385 |
| - &mut self, |
386 |
| - f: impl FnOnce(&mut Self::Bus) -> Result<R, <Self::Bus as ErrorType>::Error>, |
387 |
| - ) -> Result<R, Self::Error> { |
| 414 | + let mut op_res = Ok(()); |
| 415 | + |
| 416 | + for buf in operations { |
| 417 | + if let Err(e) = self.bus.write(buf) { |
| 418 | + op_res = Err(e); |
| 419 | + break; |
| 420 | + } |
| 421 | + } |
| 422 | + |
| 423 | + // On failure, it's important to still flush and deassert CS. |
| 424 | + let flush_res = self.bus.flush(); |
| 425 | + let cs_res = self.cs.set_high(); |
| 426 | + |
| 427 | + op_res.map_err(ExclusiveDeviceError::Spi)?; |
| 428 | + flush_res.map_err(ExclusiveDeviceError::Spi)?; |
| 429 | + cs_res.map_err(ExclusiveDeviceError::Cs)?; |
| 430 | + |
| 431 | + Ok(()) |
| 432 | + } |
| 433 | +} |
| 434 | + |
| 435 | +impl<Word: Copy + 'static, BUS, CS> blocking::SpiDevice<Word> for ExclusiveDevice<BUS, CS> |
| 436 | +where |
| 437 | + BUS: blocking::SpiBus<Word>, |
| 438 | + CS: OutputPin, |
| 439 | +{ |
| 440 | + fn transaction(&mut self, operations: &mut [Operation<'_, Word>]) -> Result<(), Self::Error> { |
388 | 441 | self.cs.set_low().map_err(ExclusiveDeviceError::Cs)?;
|
389 | 442 |
|
390 |
| - let f_res = f(&mut self.bus); |
| 443 | + let mut op_res = Ok(()); |
| 444 | + |
| 445 | + for op in operations { |
| 446 | + match op { |
| 447 | + Operation::Read(buf) => { |
| 448 | + if let Err(e) = self.bus.read(buf) { |
| 449 | + op_res = Err(e); |
| 450 | + break; |
| 451 | + } |
| 452 | + } |
| 453 | + Operation::Write(buf) => { |
| 454 | + if let Err(e) = self.bus.write(buf) { |
| 455 | + op_res = Err(e); |
| 456 | + break; |
| 457 | + } |
| 458 | + } |
| 459 | + Operation::Transfer(read, write) => { |
| 460 | + if let Err(e) = self.bus.transfer(read, write) { |
| 461 | + op_res = Err(e); |
| 462 | + break; |
| 463 | + } |
| 464 | + } |
| 465 | + Operation::TransferInPlace(buf) => { |
| 466 | + if let Err(e) = self.bus.transfer_in_place(buf) { |
| 467 | + op_res = Err(e); |
| 468 | + break; |
| 469 | + } |
| 470 | + } |
| 471 | + } |
| 472 | + } |
391 | 473 |
|
392 | 474 | // On failure, it's important to still flush and deassert CS.
|
393 | 475 | let flush_res = self.bus.flush();
|
394 | 476 | let cs_res = self.cs.set_high();
|
395 | 477 |
|
396 |
| - let f_res = f_res.map_err(ExclusiveDeviceError::Spi)?; |
| 478 | + op_res.map_err(ExclusiveDeviceError::Spi)?; |
397 | 479 | flush_res.map_err(ExclusiveDeviceError::Spi)?;
|
398 | 480 | cs_res.map_err(ExclusiveDeviceError::Cs)?;
|
399 | 481 |
|
400 |
| - Ok(f_res) |
| 482 | + Ok(()) |
401 | 483 | }
|
402 | 484 | }
|
403 | 485 |
|
|
0 commit comments