atsamd_hal/sercom/spi/impl_ehal/
mod.rs
1use super::*;
2use crate::ehal::spi::{self, SpiBus};
3#[allow(unused_imports)]
4use crate::ehal_02::{blocking, serial};
5use crate::ehal_nb;
6use num_traits::PrimInt;
7
8#[cfg(feature = "dma")]
9mod dma;
10mod panic_on;
11
12#[hal_module(
13 any("sercom0-d11", "sercom0-d21") => "thumbv6m.rs",
14 "sercom0-d5x" => "thumbv7em.rs")]
15pub mod impl_ehal_02 {}
16
17impl spi::Error for Error {
18 #[allow(unreachable_patterns)]
19 #[inline]
20 fn kind(&self) -> crate::ehal::spi::ErrorKind {
21 match self {
22 Error::Overflow => crate::ehal::spi::ErrorKind::Overrun,
23 Error::LengthError => crate::ehal::spi::ErrorKind::Other,
24 _ => crate::ehal::spi::ErrorKind::Other,
26 }
27 }
28}
29
30impl<C, D, R, T> ehal::spi::ErrorType for Spi<C, D, R, T>
31where
32 C: ValidConfig,
33 D: Capability,
34{
35 type Error = Error;
36}
37
38impl embedded_io::Error for Error {
39 fn kind(&self) -> embedded_io::ErrorKind {
40 embedded_io::ErrorKind::Other
41 }
42}
43
44impl<C, D, R, T> embedded_io::ErrorType for Spi<C, D, R, T>
45where
46 C: ValidConfig,
47 D: Capability,
48{
49 type Error = Error;
50}
51
52impl ehal_nb::serial::Error for Error {
53 #[allow(unreachable_patterns)]
54 fn kind(&self) -> ehal_nb::serial::ErrorKind {
55 match self {
56 Error::Overflow => ehal_nb::serial::ErrorKind::Overrun,
57 Error::LengthError => ehal_nb::serial::ErrorKind::Other,
58 _ => ehal_nb::serial::ErrorKind::Other,
60 }
61 }
62}
63
64impl<C, D, R, T> ehal_nb::serial::ErrorType for Spi<C, D, R, T>
65where
66 C: ValidConfig,
67 D: Capability,
68{
69 type Error = Error;
70}
71
72impl<P, M, C, D, R, T> Spi<Config<P, M, C>, D, R, T>
74where
75 Config<P, M, C>: ValidConfig,
76 P: ValidPads,
77 M: OpMode,
78 C: Size + 'static,
79 C::Word: PrimInt + AsPrimitive<DataWidth>,
80 DataWidth: AsPrimitive<C::Word>,
81 D: Capability,
82{
83 #[inline]
85 fn transfer_word_in_place(&mut self, word: C::Word) -> Result<C::Word, Error> {
86 self.block_on_flags(Flags::DRE)?;
87
88 unsafe {
89 self.write_data(word.as_());
90 }
91
92 self.flush_rx()?;
93 let word = unsafe { self.read_data().as_() };
94 Ok(word)
95 }
96
97 #[inline]
102 fn transfer_word_by_word(
103 &mut self,
104 read: &mut [C::Word],
105 write: &[C::Word],
106 ) -> Result<(), Error> {
107 let nop_word = self.config.nop_word;
108
109 for (r, w) in read
110 .iter_mut()
111 .zip(write.iter().chain(core::iter::repeat(&nop_word.as_())))
112 {
113 *r = self.transfer_word_in_place(*w)?;
114 }
115
116 Ok(())
117 }
118
119 #[inline]
121 fn flush_tx(&mut self) {
122 let _ = self.block_on_flags(Flags::TXC);
124 }
125
126 #[inline]
128 fn flush_rx(&mut self) -> Result<(), Error> {
129 self.block_on_flags(Flags::RXC)
130 }
131}
132
133impl<P, M, C, D> Spi<Config<P, M, C>, D>
135where
136 Config<P, M, C>: ValidConfig,
137 P: ValidPads,
138 M: MasterMode,
139 C: Size + 'static,
140 C::Word: PrimInt + AsPrimitive<DataWidth> + Copy,
141 D: Capability,
142 DataWidth: AsPrimitive<C::Word>,
143{
144 #[inline]
145 fn read_word_by_word(&mut self, words: &mut [Word<C>]) -> Result<(), Error> {
146 for word in words.iter_mut() {
149 *word = self.transfer_word_in_place(self.config.nop_word.as_())?;
150 }
151 Ok(())
152 }
153
154 #[inline]
155 fn write_word_by_word(&mut self, words: &[Word<C>]) -> Result<(), Error> {
156 self.config.as_mut().regs.rx_disable();
158
159 for word in words {
160 self.block_on_flags(Flags::DRE)?;
161 unsafe {
162 self.write_data(word.as_());
163 }
164 }
165
166 if D::RX_ENABLE {
168 self.config.as_mut().regs.rx_enable();
169 }
170 Ok(())
171 }
172}
173
174impl<P, M, C> SpiBus<Word<C>> for Spi<Config<P, M, C>, Duplex>
176where
177 Config<P, M, C>: ValidConfig,
178 P: ValidPads,
179 M: MasterMode,
180 C: Size + 'static,
181 C::Word: PrimInt + AsPrimitive<DataWidth> + Copy,
182 DataWidth: AsPrimitive<C::Word>,
183{
184 #[inline]
185 fn read(&mut self, words: &mut [Word<C>]) -> Result<(), Self::Error> {
186 self.read_word_by_word(words)
187 }
188
189 #[inline]
190 fn write(&mut self, words: &[Word<C>]) -> Result<(), Self::Error> {
191 self.write_word_by_word(words)
192 }
193
194 #[inline]
195 fn transfer(&mut self, read: &mut [Word<C>], write: &[Word<C>]) -> Result<(), Self::Error> {
196 self.transfer_word_by_word(read, write)
197 }
198
199 #[inline]
200 fn transfer_in_place(&mut self, words: &mut [Word<C>]) -> Result<(), Self::Error> {
201 for word in words {
202 let read = self.transfer_word_in_place(*word)?;
203 *word = read;
204 }
205
206 Ok(())
207 }
208
209 #[inline]
210 fn flush(&mut self) -> Result<(), Error> {
211 self.flush_tx();
212 Ok(())
213 }
214}