diff options
| -rw-r--r-- | embassy-stm32/src/spi.rs | 108 |
1 files changed, 88 insertions, 20 deletions
diff --git a/embassy-stm32/src/spi.rs b/embassy-stm32/src/spi.rs index b4b1d3d8c..3eec77424 100644 --- a/embassy-stm32/src/spi.rs +++ b/embassy-stm32/src/spi.rs | |||
| @@ -1,59 +1,127 @@ | |||
| 1 | #![macro_use] | ||
| 2 | |||
| 1 | pub use embedded_hal::spi::{Mode, Phase, Polarity, MODE_0, MODE_1, MODE_2, MODE_3}; | 3 | pub use embedded_hal::spi::{Mode, Phase, Polarity, MODE_0, MODE_1, MODE_2, MODE_3}; |
| 2 | use core::marker::PhantomData; | 4 | use core::marker::PhantomData; |
| 3 | use embassy::interrupt::Interrupt; | 5 | use embassy::interrupt::Interrupt; |
| 4 | use embedded_hal::blocking::spi::Write; | 6 | use embedded_hal::blocking::spi::{Write, Transfer}; |
| 5 | use crate::pac::spi | 7 | //use crate::pac::spi; |
| 6 | 8 | ||
| 7 | pub struct Spi<'d, T: Instance> { | 9 | pub struct Spi<'d, T: Instance> { |
| 8 | peri: T, | 10 | peri: T, |
| 9 | irq: T::Interrupt, | 11 | //irq: T::Interrupt, |
| 10 | phantom: PhantomData<&'d mut T>, | 12 | phantom: PhantomData<&'d mut T>, |
| 11 | } | 13 | } |
| 12 | 14 | ||
| 13 | pub enum Error { | 15 | pub enum Error { |
| 14 | 16 | Framing, | |
| 17 | Crc, | ||
| 18 | Overrun, | ||
| 15 | } | 19 | } |
| 16 | 20 | ||
| 17 | impl<'d, T: Instance> embedded_hal::blocking::spi::Write<u8> for Spim<'d, T> { | 21 | impl<'d, T: Instance> embedded_hal::blocking::spi::Write<u8> for Spi<'d, T> { |
| 18 | type Error = Error; | 22 | type Error = Error; |
| 19 | 23 | ||
| 20 | fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> { | 24 | fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> { |
| 21 | let mut recv: &mut [u8] = &mut []; | 25 | let regs = T::regs(); |
| 22 | 26 | ||
| 27 | for word in words.iter() { | ||
| 28 | while unsafe { !regs.sr().read().txe() } { | ||
| 29 | // spin | ||
| 30 | } | ||
| 31 | unsafe { | ||
| 32 | regs.dr().write(|reg| reg.0 = *word as u32); | ||
| 33 | } | ||
| 34 | loop { | ||
| 35 | let sr = unsafe { regs.sr().read() }; | ||
| 36 | if sr.fre() { | ||
| 37 | return Err(Error::Framing); | ||
| 38 | } | ||
| 39 | if sr.ovr() { | ||
| 40 | return Err(Error::Overrun); | ||
| 41 | } | ||
| 42 | if sr.crcerr() { | ||
| 43 | return Err(Error::Crc); | ||
| 44 | } | ||
| 45 | if !sr.txe() { | ||
| 46 | // loop waiting for TXE | ||
| 47 | } | ||
| 48 | } | ||
| 49 | } | ||
| 50 | |||
| 51 | Ok(()) | ||
| 23 | } | 52 | } |
| 24 | } | 53 | } |
| 25 | 54 | ||
| 26 | mod sealed { | 55 | impl<'d, T: Instance> embedded_hal::blocking::spi::Transfer<u8> for Spi<'d, T> { |
| 27 | use super::*; | 56 | type Error = Error; |
| 28 | use embassy::util::AtomicWaker; | ||
| 29 | 57 | ||
| 30 | pub struct State { | 58 | fn transfer<'w>(&mut self, words: &'w mut [u8]) -> Result<&'w [u8], Self::Error> { |
| 31 | pub end_waker: AtomicWaker, | 59 | let regs = T::regs(); |
| 32 | } | ||
| 33 | 60 | ||
| 34 | impl State { | 61 | for word in words.iter_mut() { |
| 35 | pub const fn new() -> Self { | 62 | while unsafe { !regs.sr().read().txe() } { |
| 36 | Self { | 63 | // spin |
| 37 | end_waker: AtomicWaker::new(), | 64 | } |
| 65 | unsafe { | ||
| 66 | regs.dr().write(|reg| reg.0 = *word as u32); | ||
| 67 | } | ||
| 68 | while unsafe { !regs.sr().read().rxne() } { | ||
| 69 | // spin waiting for inbound to shift in. | ||
| 70 | } | ||
| 71 | *word = unsafe { regs.dr().read().0 as u8 }; | ||
| 72 | loop { | ||
| 73 | let sr = unsafe { regs.sr().read() }; | ||
| 74 | if sr.fre() { | ||
| 75 | return Err(Error::Framing); | ||
| 76 | } | ||
| 77 | if sr.ovr() { | ||
| 78 | return Err(Error::Overrun); | ||
| 79 | } | ||
| 80 | if sr.crcerr() { | ||
| 81 | return Err(Error::Crc); | ||
| 82 | } | ||
| 83 | if !sr.txe() { | ||
| 84 | // loop waiting for TXE | ||
| 85 | } | ||
| 38 | } | 86 | } |
| 39 | } | 87 | } |
| 88 | |||
| 89 | Ok(words) | ||
| 40 | } | 90 | } |
| 91 | } | ||
| 92 | |||
| 93 | |||
| 94 | pub(crate) mod sealed { | ||
| 95 | use super::*; | ||
| 96 | use embassy::util::AtomicWaker; | ||
| 97 | |||
| 98 | //pub struct State { | ||
| 99 | //pub end_waker: AtomicWaker, | ||
| 100 | //} | ||
| 101 | |||
| 102 | //impl State { | ||
| 103 | //pub const fn new() -> Self { | ||
| 104 | //Self { | ||
| 105 | //end_waker: AtomicWaker::new(), | ||
| 106 | //} | ||
| 107 | //} | ||
| 108 | //} | ||
| 41 | 109 | ||
| 42 | pub trait Instance { | 110 | pub trait Instance { |
| 43 | fn regs() -> &'static crate::pac::spi::Spi; | 111 | fn regs() -> &'static crate::pac::spi::Spi; |
| 44 | fn state() -> &'static State; | 112 | //fn state() -> &'static State; |
| 45 | } | 113 | } |
| 46 | } | 114 | } |
| 47 | 115 | ||
| 48 | pub trait Instance: sealed::Instance + 'static { | 116 | pub trait Instance: sealed::Instance + 'static { |
| 49 | type Interrupt: Interrupt; | 117 | //type Interrupt: Interrupt; |
| 50 | } | 118 | } |
| 51 | 119 | ||
| 52 | macro_rules! impl_spi { | 120 | macro_rules! impl_spi { |
| 53 | ($inst:ident) => { | 121 | ($inst:ident) => { |
| 54 | impl crate::spi::sealed::Instance for peripherals::$inst { | 122 | impl crate::spi::sealed::Instance for peripherals::$inst { |
| 55 | fn regs() -> crate::pac::spi::Spi { | 123 | fn regs() -> &'static crate::pac::spi::Spi { |
| 56 | crate::pac::$inst | 124 | &crate::pac::$inst |
| 57 | } | 125 | } |
| 58 | } | 126 | } |
| 59 | 127 | ||
