spi.rs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474
  1. /*!
  2. # Serial Peripheral Interface
  3. ## Alternate function remapping
  4. ### SPI1
  5. | Function | Spi1NoRemap | Spi1Remap |
  6. |:----:|:-----------:|:---------:|
  7. | SCK | PA5 | PB3 |
  8. | MISO | PA6 | PB4 |
  9. | MOSI | PA7 | PB5 |
  10. ### SPI2
  11. | Function | Spi2NoRemap |
  12. |:----:|:-----------:|
  13. | SCK | PB13 |
  14. | MISO | PB14 |
  15. | MOSI | PB15 |
  16. ### SPI3
  17. Available only on high density devices.
  18. | Function | Spi3NoRemap | Spi3Remap |
  19. |:----:|:-----------:|:---------:|
  20. | SCK | PB3 | PC10 |
  21. | MISO | PB4 | PC11 |
  22. | MOSI | PB5 | PC12 |
  23. */
  24. use core::ops::Deref;
  25. use core::ptr;
  26. use nb;
  27. pub use crate::hal::spi::{FullDuplex, Mode, Phase, Polarity};
  28. #[cfg(feature = "high")]
  29. use crate::pac::SPI3;
  30. use crate::pac::{SPI1, SPI2};
  31. use crate::afio::MAPR;
  32. use crate::dma::dma1::{C3, C5};
  33. use crate::dma::{Static, Transfer, TransferPayload, Transmit, TxDma, R};
  34. use crate::gpio::gpioa::{PA5, PA6, PA7};
  35. use crate::gpio::gpiob::{PB13, PB14, PB15, PB3, PB4, PB5};
  36. use crate::gpio::{Alternate, Floating, Input, PushPull};
  37. use crate::rcc::{sealed::RccBus, Clocks, Enable, GetBusFreq, Reset};
  38. use crate::time::Hertz;
  39. use core::sync::atomic::{self, Ordering};
  40. use as_slice::AsSlice;
  41. /// SPI error
  42. #[derive(Debug)]
  43. pub enum Error {
  44. /// Overrun occurred
  45. Overrun,
  46. /// Mode fault occurred
  47. ModeFault,
  48. /// CRC error
  49. Crc,
  50. #[doc(hidden)]
  51. _Extensible,
  52. }
  53. use core::marker::PhantomData;
  54. mod sealed {
  55. pub trait Remap {
  56. type Periph;
  57. const REMAP: bool;
  58. }
  59. pub trait Sck<REMAP> {}
  60. pub trait Miso<REMAP> {}
  61. pub trait Mosi<REMAP> {}
  62. pub struct _Sck;
  63. pub struct _Miso;
  64. pub struct _Mosi;
  65. }
  66. use sealed::{Miso, Mosi, Remap, Sck};
  67. pub trait Pins<REMAP, P> {
  68. type _Pos;
  69. }
  70. macro_rules! pins_impl {
  71. ( $( ( $($PINX:ident),+ ), ( $($TRAIT:ident),+ ), ( $($POS:ident),* ); )+ ) => {
  72. $(
  73. #[allow(unused_parens)]
  74. impl<REMAP, $($PINX,)+> Pins<REMAP, ($(sealed::$POS),+)> for ($($PINX),+)
  75. where
  76. $($PINX: $TRAIT<REMAP>,)+
  77. {
  78. type _Pos = ($(sealed::$POS),+);
  79. }
  80. )+
  81. };
  82. }
  83. pins_impl!(
  84. (SCK, MISO, MOSI), (Sck, Miso, Mosi), (_Sck, _Miso, _Mosi);
  85. (SCK, MOSI, MISO), (Sck, Mosi, Miso), (_Sck, _Mosi, _Miso);
  86. (MOSI, SCK, MISO), (Mosi, Sck, Miso), (_Mosi, _Sck, _Miso);
  87. (MOSI, MISO, SCK), (Mosi, Miso, Sck), (_Mosi, _Miso, _Sck);
  88. (MISO, MOSI, SCK), (Miso, Mosi, Sck), (_Miso, _Mosi, _Sck);
  89. (MISO, SCK, MOSI), (Miso, Sck, Mosi), (_Miso, _Sck, _Mosi);
  90. );
  91. pub struct Spi<SPI, REMAP, PINS> {
  92. spi: SPI,
  93. pins: PINS,
  94. _remap: PhantomData<REMAP>,
  95. }
  96. /// A filler type for when the SCK pin is unnecessary
  97. pub struct NoSck;
  98. /// A filler type for when the Miso pin is unnecessary
  99. pub struct NoMiso;
  100. /// A filler type for when the Mosi pin is unnecessary
  101. pub struct NoMosi;
  102. impl<REMAP> Sck<REMAP> for NoSck {}
  103. impl<REMAP> Miso<REMAP> for NoMiso {}
  104. impl<REMAP> Mosi<REMAP> for NoMosi {}
  105. macro_rules! remap {
  106. ($name:ident, $SPIX:ident, $state:literal, $SCK:ident, $MISO:ident, $MOSI:ident) => {
  107. pub struct $name;
  108. impl Remap for $name {
  109. type Periph = $SPIX;
  110. const REMAP: bool = $state;
  111. }
  112. impl Sck<$name> for $SCK<Alternate<PushPull>> {}
  113. impl Miso<$name> for $MISO<Input<Floating>> {}
  114. impl Mosi<$name> for $MOSI<Alternate<PushPull>> {}
  115. };
  116. }
  117. remap!(Spi1NoRemap, SPI1, false, PA5, PA6, PA7);
  118. remap!(Spi1Remap, SPI1, true, PB3, PB4, PB5);
  119. remap!(Spi2NoRemap, SPI2, false, PB13, PB14, PB15);
  120. #[cfg(feature = "high")]
  121. remap!(Spi3NoRemap, SPI3, false, PB3, PB4, PB5);
  122. #[cfg(feature = "stm32f105")]
  123. remap!(Spi3Remap, SPI3, true, PC10, PC11, PC12);
  124. impl<REMAP, PINS> Spi<SPI1, REMAP, PINS> {
  125. pub fn spi1<F, POS>(
  126. spi: SPI1,
  127. pins: PINS,
  128. mapr: &mut MAPR,
  129. mode: Mode,
  130. freq: F,
  131. clocks: Clocks,
  132. apb: &mut <SPI1 as RccBus>::Bus,
  133. ) -> Self
  134. where
  135. F: Into<Hertz>,
  136. REMAP: Remap<Periph = SPI1>,
  137. PINS: Pins<REMAP, POS>,
  138. {
  139. mapr.modify_mapr(|_, w| w.spi1_remap().bit(REMAP::REMAP));
  140. Spi::<SPI1, _, _>::_spi(spi, pins, mode, freq.into(), clocks, apb)
  141. }
  142. }
  143. impl<REMAP, PINS> Spi<SPI2, REMAP, PINS> {
  144. pub fn spi2<F, POS>(
  145. spi: SPI2,
  146. pins: PINS,
  147. mode: Mode,
  148. freq: F,
  149. clocks: Clocks,
  150. apb: &mut <SPI2 as RccBus>::Bus,
  151. ) -> Self
  152. where
  153. F: Into<Hertz>,
  154. REMAP: Remap<Periph = SPI2>,
  155. PINS: Pins<REMAP, POS>,
  156. {
  157. Spi::<SPI2, _, _>::_spi(spi, pins, mode, freq.into(), clocks, apb)
  158. }
  159. }
  160. #[cfg(feature = "high")]
  161. impl<REMAP, PINS> Spi<SPI3, REMAP, PINS> {
  162. pub fn spi3<F, POS>(
  163. spi: SPI3,
  164. pins: PINS,
  165. mode: Mode,
  166. freq: F,
  167. clocks: Clocks,
  168. apb: &mut <SPI3 as RccBus>::Bus,
  169. ) -> Self
  170. where
  171. F: Into<Hertz>,
  172. REMAP: Remap<Periph = SPI3>,
  173. PINS: Pins<REMAP, POS>,
  174. {
  175. Spi::<SPI3, _, _>::_spi(spi, pins, mode, freq.into(), clocks, apb)
  176. }
  177. }
  178. type SpiRegisterBlock = crate::pac::spi1::RegisterBlock;
  179. impl<SPI, REMAP, PINS> Spi<SPI, REMAP, PINS>
  180. where
  181. SPI: Deref<Target = SpiRegisterBlock> + Enable + Reset,
  182. SPI::Bus: GetBusFreq,
  183. {
  184. fn _spi(
  185. spi: SPI,
  186. pins: PINS,
  187. mode: Mode,
  188. freq: Hertz,
  189. clocks: Clocks,
  190. apb: &mut SPI::Bus,
  191. ) -> Self {
  192. // enable or reset SPI
  193. SPI::enable(apb);
  194. SPI::reset(apb);
  195. // disable SS output
  196. spi.cr2.write(|w| w.ssoe().clear_bit());
  197. let br = match SPI::Bus::get_frequency(&clocks).0 / freq.0 {
  198. 0 => unreachable!(),
  199. 1..=2 => 0b000,
  200. 3..=5 => 0b001,
  201. 6..=11 => 0b010,
  202. 12..=23 => 0b011,
  203. 24..=47 => 0b100,
  204. 48..=95 => 0b101,
  205. 96..=191 => 0b110,
  206. _ => 0b111,
  207. };
  208. spi.cr1.write(|w| {
  209. w
  210. // clock phase from config
  211. .cpha()
  212. .bit(mode.phase == Phase::CaptureOnSecondTransition)
  213. // clock polarity from config
  214. .cpol()
  215. .bit(mode.polarity == Polarity::IdleHigh)
  216. // mstr: master configuration
  217. .mstr()
  218. .set_bit()
  219. // baudrate value
  220. .br()
  221. .bits(br)
  222. // lsbfirst: MSB first
  223. .lsbfirst()
  224. .clear_bit()
  225. // ssm: enable software slave management (NSS pin free for other uses)
  226. .ssm()
  227. .set_bit()
  228. // ssi: set nss high = master mode
  229. .ssi()
  230. .set_bit()
  231. // dff: 8 bit frames
  232. .dff()
  233. .clear_bit()
  234. // bidimode: 2-line unidirectional
  235. .bidimode()
  236. .clear_bit()
  237. // both TX and RX are used
  238. .rxonly()
  239. .clear_bit()
  240. // spe: enable the SPI bus
  241. .spe()
  242. .set_bit()
  243. });
  244. Spi {
  245. spi,
  246. pins,
  247. _remap: PhantomData,
  248. }
  249. }
  250. pub fn free(self) -> (SPI, PINS) {
  251. (self.spi, self.pins)
  252. }
  253. }
  254. impl<SPI, REMAP, PINS> crate::hal::spi::FullDuplex<u8> for Spi<SPI, REMAP, PINS>
  255. where
  256. SPI: Deref<Target = SpiRegisterBlock>,
  257. {
  258. type Error = Error;
  259. fn read(&mut self) -> nb::Result<u8, Error> {
  260. let sr = self.spi.sr.read();
  261. Err(if sr.ovr().bit_is_set() {
  262. nb::Error::Other(Error::Overrun)
  263. } else if sr.modf().bit_is_set() {
  264. nb::Error::Other(Error::ModeFault)
  265. } else if sr.crcerr().bit_is_set() {
  266. nb::Error::Other(Error::Crc)
  267. } else if sr.rxne().bit_is_set() {
  268. // NOTE(read_volatile) read only 1 byte (the svd2rust API only allows
  269. // reading a half-word)
  270. return Ok(unsafe { ptr::read_volatile(&self.spi.dr as *const _ as *const u8) });
  271. } else {
  272. nb::Error::WouldBlock
  273. })
  274. }
  275. fn send(&mut self, byte: u8) -> nb::Result<(), Error> {
  276. let sr = self.spi.sr.read();
  277. Err(if sr.ovr().bit_is_set() {
  278. nb::Error::Other(Error::Overrun)
  279. } else if sr.modf().bit_is_set() {
  280. nb::Error::Other(Error::ModeFault)
  281. } else if sr.crcerr().bit_is_set() {
  282. nb::Error::Other(Error::Crc)
  283. } else if sr.txe().bit_is_set() {
  284. // NOTE(write_volatile) see note above
  285. unsafe { ptr::write_volatile(&self.spi.dr as *const _ as *mut u8, byte) }
  286. return Ok(());
  287. } else {
  288. nb::Error::WouldBlock
  289. })
  290. }
  291. }
  292. impl<SPI, REMAP, PINS> crate::hal::blocking::spi::transfer::Default<u8> for Spi<SPI, REMAP, PINS> where
  293. SPI: Deref<Target = SpiRegisterBlock>
  294. {
  295. }
  296. impl<SPI, REMAP, PINS> crate::hal::blocking::spi::Write<u8> for Spi<SPI, REMAP, PINS>
  297. where
  298. SPI: Deref<Target = SpiRegisterBlock>,
  299. {
  300. type Error = Error;
  301. // Implement write as per the "Transmit only procedure" page 712
  302. // of RM0008 Rev 20. This is more than twice as fast as the
  303. // default Write<> implementation (which reads and drops each
  304. // received value)
  305. fn write(&mut self, words: &[u8]) -> Result<(), Error> {
  306. // Write each word when the tx buffer is empty
  307. for word in words {
  308. loop {
  309. let sr = self.spi.sr.read();
  310. if sr.txe().bit_is_set() {
  311. // NOTE(write_volatile) see note above
  312. unsafe { ptr::write_volatile(&self.spi.dr as *const _ as *mut u8, *word) }
  313. if sr.modf().bit_is_set() {
  314. return Err(Error::ModeFault);
  315. }
  316. break;
  317. }
  318. }
  319. }
  320. // Wait for final TXE
  321. loop {
  322. let sr = self.spi.sr.read();
  323. if sr.txe().bit_is_set() {
  324. break;
  325. }
  326. }
  327. // Wait for final !BSY
  328. loop {
  329. let sr = self.spi.sr.read();
  330. if !sr.bsy().bit_is_set() {
  331. break;
  332. }
  333. }
  334. // Clear OVR set due to dropped received values
  335. // NOTE(read_volatile) see note aboev
  336. unsafe {
  337. let _ = ptr::read_volatile(&self.spi.dr as *const _ as *const u8);
  338. }
  339. let _ = self.spi.sr.read();
  340. Ok(())
  341. }
  342. }
  343. // DMA
  344. pub struct SpiPayload<SPI, REMAP, PINS> {
  345. spi: Spi<SPI, REMAP, PINS>,
  346. }
  347. pub type SpiTxDma<SPI, REMAP, PINS, CHANNEL> = TxDma<SpiPayload<SPI, REMAP, PINS>, CHANNEL>;
  348. macro_rules! spi_dma {
  349. ($SPIi:ident, $TCi:ident) => {
  350. impl<REMAP, PINS> Transmit for SpiTxDma<$SPIi, REMAP, PINS, $TCi> {
  351. type TxChannel = $TCi;
  352. type ReceivedWord = u8;
  353. }
  354. impl<REMAP, PINS> Spi<$SPIi, REMAP, PINS> {
  355. pub fn with_tx_dma(self, channel: $TCi) -> SpiTxDma<$SPIi, REMAP, PINS, $TCi> {
  356. let payload = SpiPayload { spi: self };
  357. SpiTxDma { payload, channel }
  358. }
  359. }
  360. impl<REMAP, PINS> TransferPayload for SpiTxDma<$SPIi, REMAP, PINS, $TCi> {
  361. fn start(&mut self) {
  362. self.payload
  363. .spi
  364. .spi
  365. .cr2
  366. .modify(|_, w| w.txdmaen().set_bit());
  367. self.channel.start();
  368. }
  369. fn stop(&mut self) {
  370. self.payload
  371. .spi
  372. .spi
  373. .cr2
  374. .modify(|_, w| w.txdmaen().clear_bit());
  375. self.channel.stop();
  376. }
  377. }
  378. impl<A, B, REMAP, PIN> crate::dma::WriteDma<A, B, u8> for SpiTxDma<$SPIi, REMAP, PIN, $TCi>
  379. where
  380. A: AsSlice<Element = u8>,
  381. B: Static<A>,
  382. {
  383. fn write(mut self, buffer: B) -> Transfer<R, B, Self> {
  384. {
  385. let buffer = buffer.borrow().as_slice();
  386. self.channel.set_peripheral_address(
  387. unsafe { &(*$SPIi::ptr()).dr as *const _ as u32 },
  388. false,
  389. );
  390. self.channel
  391. .set_memory_address(buffer.as_ptr() as u32, true);
  392. self.channel.set_transfer_length(buffer.len());
  393. }
  394. atomic::compiler_fence(Ordering::Release);
  395. self.channel.ch().cr.modify(|_, w| {
  396. w
  397. // memory to memory mode disabled
  398. .mem2mem()
  399. .clear_bit()
  400. // medium channel priority level
  401. .pl()
  402. .medium()
  403. // 8-bit memory size
  404. .msize()
  405. .bits8()
  406. // 8-bit peripheral size
  407. .psize()
  408. .bits8()
  409. // circular mode disabled
  410. .circ()
  411. .clear_bit()
  412. // read from memory
  413. .dir()
  414. .set_bit()
  415. });
  416. self.start();
  417. Transfer::r(buffer, self)
  418. }
  419. }
  420. };
  421. }
  422. spi_dma!(SPI1, C3);
  423. spi_dma!(SPI2, C5);