gpio.rs 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890
  1. //! # General Purpose I/Os
  2. //!
  3. //! # Interfacing with v1 traits
  4. //!
  5. //! `embedded-hal` has two versions of the digital traits, `v2` which is used
  6. //! by this crate and `v1` which is deprecated but still used by a lot of drivers.
  7. //! If you want to use such a driver with this crate, you need to convert the digital pins to the `v1` type.
  8. //!
  9. //! This is done using `embedded-hal::digital::v1_compat::OldOutputPin`. For example:
  10. //!
  11. //! ```rust
  12. //! let nss = gpioa.pa4.into_push_pull_output(&mut gpioa.crl);
  13. //! let mut mfrc522 = Mfrc522::new(spi, OldOutputPin::from(nss)).unwrap();
  14. //! ```
  15. //!
  16. use core::marker::PhantomData;
  17. use crate::rcc::APB2;
  18. use crate::pac::EXTI;
  19. use crate::afio;
  20. /// Extension trait to split a GPIO peripheral in independent pins and registers
  21. pub trait GpioExt {
  22. /// The to split the GPIO into
  23. type Parts;
  24. /// Splits the GPIO block into independent pins and registers
  25. fn split(self, apb2: &mut APB2) -> Self::Parts;
  26. }
  27. /// Marker trait for pin mode detection.
  28. pub trait Mode<MODE> {}
  29. /// Marker trait for active states.
  30. pub trait Active {}
  31. /// Input mode (type state)
  32. pub struct Input<MODE> {
  33. _mode: PhantomData<MODE>,
  34. }
  35. impl<MODE> Active for Input<MODE> {}
  36. /// Used by the debugger (type state)
  37. pub struct Debugger;
  38. /// Floating input (type state)
  39. pub struct Floating;
  40. /// Pulled down input (type state)
  41. pub struct PullDown;
  42. /// Pulled up input (type state)
  43. pub struct PullUp;
  44. /// Output mode (type state)
  45. pub struct Output<MODE> {
  46. _mode: PhantomData<MODE>,
  47. }
  48. impl<MODE> Active for Output<MODE> {}
  49. /// Push pull output (type state)
  50. pub struct PushPull;
  51. /// Open drain output (type state)
  52. pub struct OpenDrain;
  53. /// Analog mode (type state)
  54. pub struct Analog;
  55. impl Active for Analog {}
  56. /// Alternate function
  57. pub struct Alternate<MODE> {
  58. _mode: PhantomData<MODE>,
  59. }
  60. impl<MODE> Active for Alternate<MODE> {}
  61. pub enum State {
  62. High,
  63. Low,
  64. }
  65. // Using SCREAMING_SNAKE_CASE to be consistent with other HALs
  66. // see 59b2740 and #125 for motivation
  67. #[allow(non_camel_case_types)]
  68. #[derive(Debug, PartialEq)]
  69. pub enum Edge {
  70. RISING,
  71. FALLING,
  72. RISING_FALLING,
  73. }
  74. /// External Interrupt Pin
  75. pub trait ExtiPin {
  76. fn make_interrupt_source(&mut self, afio: &mut afio::Parts);
  77. fn trigger_on_edge(&mut self, exti: &EXTI, level: Edge);
  78. fn enable_interrupt(&mut self, exti: &EXTI);
  79. fn disable_interrupt(&mut self, exti: &EXTI);
  80. fn clear_interrupt_pending_bit(&mut self);
  81. fn check_interrupt(&mut self) -> bool;
  82. }
  83. macro_rules! gpio {
  84. ($GPIOX:ident, $gpiox:ident, $gpioy:ident, $PXx:ident, $extigpionr:expr, [
  85. $($PXi:ident: ($pxi:ident, $i:expr, $MODE:ty, $CR:ident, $exticri:ident),)+
  86. ]) => {
  87. /// GPIO
  88. pub mod $gpiox {
  89. use core::convert::Infallible;
  90. use core::marker::PhantomData;
  91. use crate::hal::digital::v2::{InputPin, OutputPin, StatefulOutputPin, toggleable};
  92. use crate::pac::{$gpioy, $GPIOX};
  93. use crate::pac::EXTI;
  94. use crate::afio;
  95. use crate::rcc::{APB2, Enable, Reset};
  96. use super::{
  97. Alternate, Floating, GpioExt, Input,
  98. OpenDrain,
  99. Output,
  100. PullDown,
  101. PullUp,
  102. PushPull,
  103. Analog,
  104. State,
  105. Active,
  106. Debugger,
  107. Pxx,
  108. Mode,
  109. Edge,
  110. ExtiPin
  111. };
  112. /// GPIO parts
  113. pub struct Parts {
  114. /// Opaque CRL register
  115. pub crl: CRL,
  116. /// Opaque CRH register
  117. pub crh: CRH,
  118. $(
  119. /// Pin
  120. pub $pxi: $PXi<$MODE>,
  121. )+
  122. }
  123. impl GpioExt for $GPIOX {
  124. type Parts = Parts;
  125. fn split(self, apb: &mut APB2) -> Parts {
  126. $GPIOX::enable(apb);
  127. $GPIOX::reset(apb);
  128. Parts {
  129. crl: CRL { _0: () },
  130. crh: CRH { _0: () },
  131. $(
  132. $pxi: $PXi { _mode: PhantomData },
  133. )+
  134. }
  135. }
  136. }
  137. /// Opaque CRL register
  138. pub struct CRL {
  139. _0: (),
  140. }
  141. impl CRL {
  142. // NOTE(allow) we get a warning on GPIOC because it only has 3 high pins
  143. #[allow(dead_code)]
  144. pub(crate) fn cr(&mut self) -> &$gpioy::CRL {
  145. unsafe { &(*$GPIOX::ptr()).crl }
  146. }
  147. }
  148. /// Opaque CRH register
  149. pub struct CRH {
  150. _0: (),
  151. }
  152. impl CRH {
  153. pub(crate) fn cr(&mut self) -> &$gpioy::CRH {
  154. unsafe { &(*$GPIOX::ptr()).crh }
  155. }
  156. }
  157. /// Partially erased pin. Only used in the Pxx enum
  158. pub struct Generic<MODE> {
  159. i: u8,
  160. _mode: PhantomData<MODE>,
  161. }
  162. impl<MODE> Generic<MODE> {
  163. pub fn downgrade(self) -> Pxx<MODE> {
  164. Pxx::$PXx(self)
  165. }
  166. }
  167. impl<MODE> OutputPin for Generic<Output<MODE>> {
  168. type Error = Infallible;
  169. fn set_high(&mut self) -> Result<(), Self::Error> {
  170. // NOTE(unsafe) atomic write to a stateless register
  171. Ok(unsafe { (*$GPIOX::ptr()).bsrr.write(|w| w.bits(1 << self.i)) })
  172. }
  173. fn set_low(&mut self) -> Result<(), Self::Error> {
  174. // NOTE(unsafe) atomic write to a stateless register
  175. Ok(unsafe { (*$GPIOX::ptr()).bsrr.write(|w| w.bits(1 << (16 + self.i))) })
  176. }
  177. }
  178. impl<MODE> InputPin for Generic<Input<MODE>> {
  179. type Error = Infallible;
  180. fn is_high(&self) -> Result<bool, Self::Error> {
  181. self.is_low().map(|b| !b)
  182. }
  183. fn is_low(&self) -> Result<bool, Self::Error> {
  184. // NOTE(unsafe) atomic read with no side effects
  185. Ok(unsafe { (*$GPIOX::ptr()).idr.read().bits() & (1 << self.i) == 0 })
  186. }
  187. }
  188. impl<MODE> ExtiPin for Generic<Input<MODE>> {
  189. /// Make corresponding EXTI line sensitive to this pin
  190. fn make_interrupt_source(&mut self, afio: &mut afio::Parts) {
  191. let offset = 4 * (self.i % 4);
  192. match self.i {
  193. 0..=3 => {
  194. afio.exticr1.exticr1().modify(|r, w| unsafe {
  195. w.bits((r.bits() & !(0xf << offset)) | ($extigpionr << offset))
  196. });
  197. },
  198. 4..=7 => {
  199. afio.exticr2.exticr2().modify(|r, w| unsafe {
  200. w.bits((r.bits() & !(0xf << offset)) | ($extigpionr << offset))
  201. });
  202. },
  203. 8..=11 => {
  204. afio.exticr3.exticr3().modify(|r, w| unsafe {
  205. w.bits((r.bits() & !(0xf << offset)) | ($extigpionr << offset))
  206. });
  207. },
  208. 12..=15 => {
  209. afio.exticr4.exticr4().modify(|r, w| unsafe {
  210. w.bits((r.bits() & !(0xf << offset)) | ($extigpionr << offset))
  211. });
  212. },
  213. _ => unreachable!(),
  214. }
  215. }
  216. /// Generate interrupt on rising edge, falling edge or both
  217. fn trigger_on_edge(&mut self, exti: &EXTI, edge: Edge) {
  218. match edge {
  219. Edge::RISING => {
  220. exti.rtsr.modify(|r, w| unsafe { w.bits(r.bits() | (1 << self.i)) });
  221. exti.ftsr.modify(|r, w| unsafe { w.bits(r.bits() & !(1 << self.i)) });
  222. },
  223. Edge::FALLING => {
  224. exti.ftsr.modify(|r, w| unsafe { w.bits(r.bits() | (1 << self.i)) });
  225. exti.rtsr.modify(|r, w| unsafe { w.bits(r.bits() & !(1 << self.i)) });
  226. },
  227. Edge::RISING_FALLING => {
  228. exti.rtsr.modify(|r, w| unsafe { w.bits(r.bits() | (1 << self.i)) });
  229. exti.ftsr.modify(|r, w| unsafe { w.bits(r.bits() | (1 << self.i)) });
  230. }
  231. }
  232. }
  233. /// Enable external interrupts from this pin.
  234. fn enable_interrupt(&mut self, exti: &EXTI) {
  235. exti.imr.modify(|r, w| unsafe { w.bits(r.bits() | (1 << self.i)) });
  236. }
  237. /// Disable external interrupts from this pin
  238. fn disable_interrupt(&mut self, exti: &EXTI) {
  239. exti.imr.modify(|r, w| unsafe { w.bits(r.bits() & !(1 << self.i)) });
  240. }
  241. /// Clear the interrupt pending bit for this pin
  242. fn clear_interrupt_pending_bit(&mut self) {
  243. unsafe { (*EXTI::ptr()).pr.write(|w| w.bits(1 << self.i) ) };
  244. }
  245. /// Reads the interrupt pending bit for this pin
  246. fn check_interrupt(&mut self) -> bool {
  247. unsafe { ((*EXTI::ptr()).pr.read().bits() & (1 << self.i)) != 0 }
  248. }
  249. }
  250. impl <MODE> StatefulOutputPin for Generic<Output<MODE>> {
  251. fn is_set_high(&self) -> Result<bool, Self::Error> {
  252. self.is_set_low().map(|b| !b)
  253. }
  254. fn is_set_low(&self) -> Result<bool, Self::Error> {
  255. // NOTE(unsafe) atomic read with no side effects
  256. Ok(unsafe { (*$GPIOX::ptr()).odr.read().bits() & (1 << self.i) == 0 })
  257. }
  258. }
  259. impl <MODE> toggleable::Default for Generic<Output<MODE>> {}
  260. impl InputPin for Generic<Output<OpenDrain>> {
  261. type Error = Infallible;
  262. fn is_high(&self) -> Result<bool, Self::Error> {
  263. self.is_low().map(|b| !b)
  264. }
  265. fn is_low(&self) -> Result<bool, Self::Error> {
  266. // NOTE(unsafe) atomic read with no side effects
  267. Ok(unsafe { (*$GPIOX::ptr()).idr.read().bits() & (1 << self.i) == 0 })
  268. }
  269. }
  270. pub type $PXx<MODE> = Pxx<MODE>;
  271. impl<MODE> Mode<MODE> for Generic<MODE> {}
  272. $(
  273. /// Pin
  274. pub struct $PXi<MODE> {
  275. _mode: PhantomData<MODE>,
  276. }
  277. impl<MODE> Mode<MODE> for $PXi<MODE> {}
  278. impl $PXi<Debugger> {
  279. /// Put the pin in an active state. The caller
  280. /// must enforce that the pin is really in this
  281. /// state in the hardware.
  282. #[allow(dead_code)]
  283. pub(crate) unsafe fn activate(self) -> $PXi<Input<Floating>> {
  284. $PXi { _mode: PhantomData }
  285. }
  286. }
  287. impl<MODE> $PXi<MODE> where MODE: Active {
  288. /// Configures the pin to operate as an alternate function push-pull output
  289. /// pin.
  290. pub fn into_alternate_push_pull(
  291. self,
  292. cr: &mut $CR,
  293. ) -> $PXi<Alternate<PushPull>> {
  294. const OFFSET: u32 = (4 * $i) % 32;
  295. // Alternate function output push pull
  296. const CNF: u32 = 0b10;
  297. // Output mode, max speed 50 MHz
  298. const MODE: u32 = 0b11;
  299. const BITS: u32 = (CNF << 2) | MODE;
  300. // input mode
  301. cr
  302. .cr()
  303. .modify(|r, w| unsafe {
  304. w.bits((r.bits() & !(0b1111 << OFFSET)) | (BITS << OFFSET))
  305. });
  306. $PXi { _mode: PhantomData }
  307. }
  308. /// Configures the pin to operate as an alternate function open-drain output
  309. /// pin.
  310. pub fn into_alternate_open_drain(
  311. self,
  312. cr: &mut $CR,
  313. ) -> $PXi<Alternate<OpenDrain>> {
  314. const OFFSET: u32 = (4 * $i) % 32;
  315. // Alternate function output open drain
  316. const CNF: u32 = 0b11;
  317. // Output mode, max speed 50 MHz
  318. const MODE: u32 = 0b11;
  319. const BITS: u32 = (CNF << 2) | MODE;
  320. // input mode
  321. cr
  322. .cr()
  323. .modify(|r, w| unsafe {
  324. w.bits((r.bits() & !(0b1111 << OFFSET)) | (BITS << OFFSET))
  325. });
  326. $PXi { _mode: PhantomData }
  327. }
  328. /// Configures the pin to operate as a floating input pin
  329. pub fn into_floating_input(
  330. self,
  331. cr: &mut $CR,
  332. ) -> $PXi<Input<Floating>> {
  333. const OFFSET: u32 = (4 * $i) % 32;
  334. // Floating input
  335. const CNF: u32 = 0b01;
  336. // Input mode
  337. const MODE: u32 = 0b00;
  338. const BITS: u32 = (CNF << 2) | MODE;
  339. // input mode
  340. cr
  341. .cr()
  342. .modify(|r, w| unsafe {
  343. w.bits((r.bits() & !(0b1111 << OFFSET)) | (BITS << OFFSET))
  344. });
  345. $PXi { _mode: PhantomData }
  346. }
  347. /// Configures the pin to operate as a pulled down input pin
  348. pub fn into_pull_down_input(
  349. self,
  350. cr: &mut $CR,
  351. ) -> $PXi<Input<PullDown>> {
  352. const OFFSET: u32 = (4 * $i) % 32;
  353. // Pull up/down input
  354. const CNF: u32 = 0b10;
  355. // Input mode
  356. const MODE: u32 = 0b00;
  357. const BITS: u32 = (CNF << 2) | MODE;
  358. //pull down:
  359. // NOTE(unsafe) atomic write to a stateless register
  360. unsafe { (*$GPIOX::ptr()).bsrr.write(|w| w.bits(1 << (16 + $i))) }
  361. // input mode
  362. cr
  363. .cr()
  364. .modify(|r, w| unsafe {
  365. w.bits((r.bits() & !(0b1111 << OFFSET)) | (BITS << OFFSET))
  366. });
  367. $PXi { _mode: PhantomData }
  368. }
  369. /// Configures the pin to operate as a pulled up input pin
  370. pub fn into_pull_up_input(
  371. self,
  372. cr: &mut $CR,
  373. ) -> $PXi<Input<PullUp>> {
  374. const OFFSET: u32 = (4 * $i) % 32;
  375. // Pull up/down input
  376. const CNF: u32 = 0b10;
  377. // Input mode
  378. const MODE: u32 = 0b00;
  379. const BITS: u32 = (CNF << 2) | MODE;
  380. //pull up:
  381. // NOTE(unsafe) atomic write to a stateless register
  382. unsafe { (*$GPIOX::ptr()).bsrr.write(|w| w.bits(1 << $i)) }
  383. // input mode
  384. cr
  385. .cr()
  386. .modify(|r, w| unsafe {
  387. w.bits((r.bits() & !(0b1111 << OFFSET)) | (BITS << OFFSET))
  388. });
  389. $PXi { _mode: PhantomData }
  390. }
  391. /// Configures the pin to operate as an open-drain output pin.
  392. /// Initial state will be low.
  393. pub fn into_open_drain_output(
  394. self,
  395. cr: &mut $CR,
  396. ) -> $PXi<Output<OpenDrain>> {
  397. self.into_open_drain_output_with_state(cr, State::Low)
  398. }
  399. /// Configures the pin to operate as an open-drain output pin.
  400. /// `initial_state` specifies whether the pin should be initially high or low.
  401. pub fn into_open_drain_output_with_state(
  402. self,
  403. cr: &mut $CR,
  404. initial_state: State,
  405. ) -> $PXi<Output<OpenDrain>> {
  406. const OFFSET: u32 = (4 * $i) % 32;
  407. // General purpose output open-drain
  408. const CNF: u32 = 0b01;
  409. // Open-Drain Output mode, max speed 50 MHz
  410. const MODE: u32 = 0b11;
  411. const BITS: u32 = (CNF << 2) | MODE;
  412. let mut res = $PXi { _mode: PhantomData };
  413. match initial_state {
  414. State::High => res.set_high(),
  415. State::Low => res.set_low(),
  416. }.unwrap();
  417. cr
  418. .cr()
  419. .modify(|r, w| unsafe {
  420. w.bits((r.bits() & !(0b1111 << OFFSET)) | (BITS << OFFSET))
  421. });
  422. res
  423. }
  424. /// Configures the pin to operate as an push-pull output pin.
  425. /// Initial state will be low.
  426. pub fn into_push_pull_output(
  427. self,
  428. cr: &mut $CR,
  429. ) -> $PXi<Output<PushPull>> {
  430. self.into_push_pull_output_with_state(cr, State::Low)
  431. }
  432. /// Configures the pin to operate as an push-pull output pin.
  433. /// `initial_state` specifies whether the pin should be initially high or low.
  434. pub fn into_push_pull_output_with_state(
  435. self,
  436. cr: &mut $CR,
  437. initial_state: State,
  438. ) -> $PXi<Output<PushPull>> {
  439. const OFFSET: u32 = (4 * $i) % 32;
  440. // General purpose output push-pull
  441. const CNF: u32 = 0b00;
  442. // Output mode, max speed 50 MHz
  443. const MODE: u32 = 0b11;
  444. const BITS: u32 = (CNF << 2) | MODE;
  445. let mut res = $PXi { _mode: PhantomData };
  446. match initial_state {
  447. State::High => res.set_high(),
  448. State::Low => res.set_low(),
  449. }.unwrap();
  450. cr
  451. .cr()
  452. .modify(|r, w| unsafe {
  453. w.bits((r.bits() & !(0b1111 << OFFSET)) | (BITS << OFFSET))
  454. });
  455. res
  456. }
  457. /// Configures the pin to operate as an analog input pin
  458. pub fn into_analog(self, cr: &mut $CR) -> $PXi<Analog> {
  459. const OFFSET: u32 = (4 * $i) % 32;
  460. // Analog input
  461. const CNF: u32 = 0b00;
  462. // Input mode
  463. const MODE: u32 = 0b00;
  464. const BITS: u32 = (CNF << 2) | MODE;
  465. // analog mode
  466. cr
  467. .cr()
  468. .modify(|r, w| unsafe {
  469. w.bits((r.bits() & !(0b1111 << OFFSET)) | (BITS << OFFSET))
  470. });
  471. $PXi { _mode: PhantomData }
  472. }
  473. }
  474. impl<MODE> $PXi<MODE> where MODE: Active {
  475. /// Erases the pin number from the type
  476. fn into_generic(self) -> Generic<MODE> {
  477. Generic {
  478. i: $i,
  479. _mode: self._mode,
  480. }
  481. }
  482. /// Erases the pin number and port from the type
  483. ///
  484. /// This is useful when you want to collect the pins into an array where you
  485. /// need all the elements to have the same type
  486. pub fn downgrade(self) -> Pxx<MODE> {
  487. self.into_generic().downgrade()
  488. }
  489. }
  490. impl<MODE> OutputPin for $PXi<Output<MODE>> {
  491. type Error = Infallible;
  492. fn set_high(&mut self) -> Result<(), Self::Error> {
  493. // NOTE(unsafe) atomic write to a stateless register
  494. Ok(unsafe { (*$GPIOX::ptr()).bsrr.write(|w| w.bits(1 << $i)) })
  495. }
  496. fn set_low(&mut self) -> Result<(), Self::Error> {
  497. // NOTE(unsafe) atomic write to a stateless register
  498. Ok(unsafe { (*$GPIOX::ptr()).bsrr.write(|w| w.bits(1 << (16 + $i))) })
  499. }
  500. }
  501. impl<MODE> StatefulOutputPin for $PXi<Output<MODE>> {
  502. fn is_set_high(&self) -> Result<bool, Self::Error> {
  503. self.is_set_low().map(|b| !b)
  504. }
  505. fn is_set_low(&self) -> Result<bool, Self::Error> {
  506. // NOTE(unsafe) atomic read with no side effects
  507. Ok(unsafe { (*$GPIOX::ptr()).odr.read().bits() & (1 << $i) == 0 })
  508. }
  509. }
  510. impl<MODE> toggleable::Default for $PXi<Output<MODE>> {}
  511. impl<MODE> InputPin for $PXi<Input<MODE>> {
  512. type Error = Infallible;
  513. fn is_high(&self) -> Result<bool, Self::Error> {
  514. self.is_low().map(|b| !b)
  515. }
  516. fn is_low(&self) -> Result<bool, Self::Error> {
  517. // NOTE(unsafe) atomic read with no side effects
  518. Ok(unsafe { (*$GPIOX::ptr()).idr.read().bits() & (1 << $i) == 0 })
  519. }
  520. }
  521. impl InputPin for $PXi<Output<OpenDrain>> {
  522. type Error = Infallible;
  523. fn is_high(&self) -> Result<bool, Self::Error> {
  524. self.is_low().map(|b| !b)
  525. }
  526. fn is_low(&self) -> Result<bool, Self::Error> {
  527. // NOTE(unsafe) atomic read with no side effects
  528. Ok(unsafe { (*$GPIOX::ptr()).idr.read().bits() & (1 << $i) == 0 })
  529. }
  530. }
  531. impl<MODE> ExtiPin for $PXi<Input<MODE>> {
  532. /// Configure EXTI Line $i to trigger from this pin.
  533. fn make_interrupt_source(&mut self, afio: &mut afio::Parts) {
  534. let offset = 4 * ($i % 4);
  535. afio.$exticri.$exticri().modify(|r, w| unsafe {
  536. let mut exticr = r.bits();
  537. exticr = (exticr & !(0xf << offset)) | ($extigpionr << offset);
  538. w.bits(exticr)
  539. });
  540. }
  541. /// Generate interrupt on rising edge, falling edge or both
  542. fn trigger_on_edge(&mut self, exti: &EXTI, edge: Edge) {
  543. match edge {
  544. Edge::RISING => {
  545. exti.rtsr.modify(|r, w| unsafe { w.bits(r.bits() | (1 << $i)) });
  546. exti.ftsr.modify(|r, w| unsafe { w.bits(r.bits() & !(1 << $i)) });
  547. },
  548. Edge::FALLING => {
  549. exti.ftsr.modify(|r, w| unsafe { w.bits(r.bits() | (1 << $i)) });
  550. exti.rtsr.modify(|r, w| unsafe { w.bits(r.bits() & !(1 << $i)) });
  551. },
  552. Edge::RISING_FALLING => {
  553. exti.rtsr.modify(|r, w| unsafe { w.bits(r.bits() | (1 << $i)) });
  554. exti.ftsr.modify(|r, w| unsafe { w.bits(r.bits() | (1 << $i)) });
  555. }
  556. }
  557. }
  558. /// Enable external interrupts from this pin.
  559. fn enable_interrupt(&mut self, exti: &EXTI) {
  560. exti.imr.modify(|r, w| unsafe { w.bits(r.bits() | (1 << $i)) });
  561. }
  562. /// Disable external interrupts from this pin
  563. fn disable_interrupt(&mut self, exti: &EXTI) {
  564. exti.imr.modify(|r, w| unsafe { w.bits(r.bits() & !(1 << $i)) });
  565. }
  566. /// Clear the interrupt pending bit for this pin
  567. fn clear_interrupt_pending_bit(&mut self) {
  568. unsafe { (*EXTI::ptr()).pr.write(|w| w.bits(1 << $i) ) };
  569. }
  570. /// Reads the interrupt pending bit for this pin
  571. fn check_interrupt(&mut self) -> bool {
  572. unsafe { ((*EXTI::ptr()).pr.read().bits() & (1 << $i)) != 0 }
  573. }
  574. }
  575. )+
  576. }
  577. }
  578. }
  579. macro_rules! impl_pxx {
  580. ($(($port:ident :: $pin:ident)),*) => {
  581. use embedded_hal::digital::v2::{InputPin, StatefulOutputPin, OutputPin};
  582. use core::convert::Infallible;
  583. pub enum Pxx<MODE> {
  584. $(
  585. $pin($port::Generic<MODE>)
  586. ),*
  587. }
  588. impl<MODE> OutputPin for Pxx<Output<MODE>> {
  589. type Error = Infallible;
  590. fn set_high(&mut self) -> Result<(), Infallible> {
  591. match self {
  592. $(Pxx::$pin(pin) => pin.set_high()),*
  593. }
  594. }
  595. fn set_low(&mut self) -> Result<(), Infallible> {
  596. match self {
  597. $(Pxx::$pin(pin) => pin.set_low()),*
  598. }
  599. }
  600. }
  601. impl<MODE> StatefulOutputPin for Pxx<Output<MODE>> {
  602. fn is_set_high(&self) -> Result<bool, Self::Error> {
  603. match self {
  604. $(Pxx::$pin(pin) => pin.is_set_high()),*
  605. }
  606. }
  607. fn is_set_low(&self) -> Result<bool, Self::Error> {
  608. match self {
  609. $(Pxx::$pin(pin) => pin.is_set_low()),*
  610. }
  611. }
  612. }
  613. impl<MODE> InputPin for Pxx<Input<MODE>> {
  614. type Error = Infallible;
  615. fn is_high(&self) -> Result<bool, Infallible> {
  616. match self {
  617. $(Pxx::$pin(pin) => pin.is_high()),*
  618. }
  619. }
  620. fn is_low(&self) -> Result<bool, Infallible> {
  621. match self {
  622. $(Pxx::$pin(pin) => pin.is_low()),*
  623. }
  624. }
  625. }
  626. impl InputPin for Pxx<Output<OpenDrain>> {
  627. type Error = Infallible;
  628. fn is_high(&self) -> Result<bool, Infallible> {
  629. match self {
  630. $(Pxx::$pin(pin) => pin.is_high()),*
  631. }
  632. }
  633. fn is_low(&self) -> Result<bool, Infallible> {
  634. match self {
  635. $(Pxx::$pin(pin) => pin.is_low()),*
  636. }
  637. }
  638. }
  639. impl<MODE> ExtiPin for Pxx<Input<MODE>> {
  640. fn make_interrupt_source(&mut self, afio: &mut afio::Parts) {
  641. match self {
  642. $(Pxx::$pin(pin) => pin.make_interrupt_source(afio)),*
  643. }
  644. }
  645. fn trigger_on_edge(&mut self, exti: &EXTI, level: Edge) {
  646. match self {
  647. $(Pxx::$pin(pin) => pin.trigger_on_edge(exti, level)),*
  648. }
  649. }
  650. fn enable_interrupt(&mut self, exti: &EXTI) {
  651. match self {
  652. $(Pxx::$pin(pin) => pin.enable_interrupt(exti)),*
  653. }
  654. }
  655. fn disable_interrupt(&mut self, exti: &EXTI) {
  656. match self {
  657. $(Pxx::$pin(pin) => pin.disable_interrupt(exti)),*
  658. }
  659. }
  660. fn clear_interrupt_pending_bit(&mut self) {
  661. match self {
  662. $(Pxx::$pin(pin) => pin.clear_interrupt_pending_bit()),*
  663. }
  664. }
  665. fn check_interrupt(&mut self) -> bool {
  666. match self {
  667. $(Pxx::$pin(pin) => pin.check_interrupt()),*
  668. }
  669. }
  670. }
  671. }
  672. }
  673. impl_pxx!{
  674. (gpioa::PAx),
  675. (gpiob::PBx),
  676. (gpioc::PCx),
  677. (gpiod::PDx),
  678. (gpioe::PEx)
  679. }
  680. gpio!(GPIOA, gpioa, gpioa, PAx, 0, [
  681. PA0: (pa0, 0, Input<Floating>, CRL, exticr1),
  682. PA1: (pa1, 1, Input<Floating>, CRL, exticr1),
  683. PA2: (pa2, 2, Input<Floating>, CRL, exticr1),
  684. PA3: (pa3, 3, Input<Floating>, CRL, exticr1),
  685. PA4: (pa4, 4, Input<Floating>, CRL, exticr2),
  686. PA5: (pa5, 5, Input<Floating>, CRL, exticr2),
  687. PA6: (pa6, 6, Input<Floating>, CRL, exticr2),
  688. PA7: (pa7, 7, Input<Floating>, CRL, exticr2),
  689. PA8: (pa8, 8, Input<Floating>, CRH, exticr3),
  690. PA9: (pa9, 9, Input<Floating>, CRH, exticr3),
  691. PA10: (pa10, 10, Input<Floating>, CRH, exticr3),
  692. PA11: (pa11, 11, Input<Floating>, CRH, exticr3),
  693. PA12: (pa12, 12, Input<Floating>, CRH, exticr4),
  694. PA13: (pa13, 13, Debugger, CRH, exticr4),
  695. PA14: (pa14, 14, Debugger, CRH, exticr4),
  696. PA15: (pa15, 15, Debugger, CRH, exticr4),
  697. ]);
  698. gpio!(GPIOB, gpiob, gpioa, PBx, 1, [
  699. PB0: (pb0, 0, Input<Floating>, CRL, exticr1),
  700. PB1: (pb1, 1, Input<Floating>, CRL, exticr1),
  701. PB2: (pb2, 2, Input<Floating>, CRL, exticr1),
  702. PB3: (pb3, 3, Debugger, CRL, exticr1),
  703. PB4: (pb4, 4, Debugger, CRL, exticr2),
  704. PB5: (pb5, 5, Input<Floating>, CRL, exticr2),
  705. PB6: (pb6, 6, Input<Floating>, CRL, exticr2),
  706. PB7: (pb7, 7, Input<Floating>, CRL, exticr2),
  707. PB8: (pb8, 8, Input<Floating>, CRH, exticr3),
  708. PB9: (pb9, 9, Input<Floating>, CRH, exticr3),
  709. PB10: (pb10, 10, Input<Floating>, CRH, exticr3),
  710. PB11: (pb11, 11, Input<Floating>, CRH, exticr3),
  711. PB12: (pb12, 12, Input<Floating>, CRH, exticr4),
  712. PB13: (pb13, 13, Input<Floating>, CRH, exticr4),
  713. PB14: (pb14, 14, Input<Floating>, CRH, exticr4),
  714. PB15: (pb15, 15, Input<Floating>, CRH, exticr4),
  715. ]);
  716. gpio!(GPIOC, gpioc, gpioa, PCx, 2, [
  717. PC0: (pc0, 0, Input<Floating>, CRL, exticr1),
  718. PC1: (pc1, 1, Input<Floating>, CRL, exticr1),
  719. PC2: (pc2, 2, Input<Floating>, CRL, exticr1),
  720. PC3: (pc3, 3, Input<Floating>, CRL, exticr1),
  721. PC4: (pc4, 4, Input<Floating>, CRL, exticr2),
  722. PC5: (pc5, 5, Input<Floating>, CRL, exticr2),
  723. PC6: (pc6, 6, Input<Floating>, CRL, exticr2),
  724. PC7: (pc7, 7, Input<Floating>, CRL, exticr2),
  725. PC8: (pc8, 8, Input<Floating>, CRH, exticr3),
  726. PC9: (pc9, 9, Input<Floating>, CRH, exticr3),
  727. PC10: (pc10, 10, Input<Floating>, CRH, exticr3),
  728. PC11: (pc11, 11, Input<Floating>, CRH, exticr3),
  729. PC12: (pc12, 12, Input<Floating>, CRH, exticr4),
  730. PC13: (pc13, 13, Input<Floating>, CRH, exticr4),
  731. PC14: (pc14, 14, Input<Floating>, CRH, exticr4),
  732. PC15: (pc15, 15, Input<Floating>, CRH, exticr4),
  733. ]);
  734. gpio!(GPIOD, gpiod, gpioa, PDx, 3, [
  735. PD0: (pd0, 0, Input<Floating>, CRL, exticr1),
  736. PD1: (pd1, 1, Input<Floating>, CRL, exticr1),
  737. PD2: (pd2, 2, Input<Floating>, CRL, exticr1),
  738. PD3: (pd3, 3, Input<Floating>, CRL, exticr1),
  739. PD4: (pd4, 4, Input<Floating>, CRL, exticr2),
  740. PD5: (pd5, 5, Input<Floating>, CRL, exticr2),
  741. PD6: (pd6, 6, Input<Floating>, CRL, exticr2),
  742. PD7: (pd7, 7, Input<Floating>, CRL, exticr2),
  743. PD8: (pd8, 8, Input<Floating>, CRH, exticr3),
  744. PD9: (pd9, 9, Input<Floating>, CRH, exticr3),
  745. PD10: (pd10, 10, Input<Floating>, CRH, exticr3),
  746. PD11: (pd11, 11, Input<Floating>, CRH, exticr3),
  747. PD12: (pd12, 12, Input<Floating>, CRH, exticr4),
  748. PD13: (pd13, 13, Input<Floating>, CRH, exticr4),
  749. PD14: (pd14, 14, Input<Floating>, CRH, exticr4),
  750. PD15: (pd15, 15, Input<Floating>, CRH, exticr4),
  751. ]);
  752. gpio!(GPIOE, gpioe, gpioa, PEx, 4, [
  753. PE0: (pe0, 0, Input<Floating>, CRL, exticr1),
  754. PE1: (pe1, 1, Input<Floating>, CRL, exticr1),
  755. PE2: (pe2, 2, Input<Floating>, CRL, exticr1),
  756. PE3: (pe3, 3, Input<Floating>, CRL, exticr1),
  757. PE4: (pe4, 4, Input<Floating>, CRL, exticr2),
  758. PE5: (pe5, 5, Input<Floating>, CRL, exticr2),
  759. PE6: (pe6, 6, Input<Floating>, CRL, exticr2),
  760. PE7: (pe7, 7, Input<Floating>, CRL, exticr2),
  761. PE8: (pe8, 8, Input<Floating>, CRH, exticr3),
  762. PE9: (pe9, 9, Input<Floating>, CRH, exticr3),
  763. PE10: (pe10, 10, Input<Floating>, CRH, exticr3),
  764. PE11: (pe11, 11, Input<Floating>, CRH, exticr3),
  765. PE12: (pe12, 12, Input<Floating>, CRH, exticr4),
  766. PE13: (pe13, 13, Input<Floating>, CRH, exticr4),
  767. PE14: (pe14, 14, Input<Floating>, CRH, exticr4),
  768. PE15: (pe15, 15, Input<Floating>, CRH, exticr4),
  769. ]);