gpio.rs 52 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372
  1. //! # General Purpose I/Os
  2. //!
  3. //! The GPIO pins are organised into groups of 16 pins which can be accessed through the
  4. //! `gpioa`, `gpiob`... modules. To get access to the pins, you first need to convert them into a
  5. //! HAL designed struct from the `pac` struct using the [split](trait.GpioExt.html#tymethod.split) function.
  6. //! ```rust
  7. //! // Acquire the GPIOC peripheral
  8. //! // NOTE: `dp` is the device peripherals from the `PAC` crate
  9. //! let mut gpioa = dp.GPIOA.split(&mut rcc.apb2);
  10. //! ```
  11. //!
  12. //! See the documentation for [rcc::APB2](../rcc/struct.APB2.html) for details about the input parameter to
  13. //! `split`.
  14. //!
  15. //! This gives you a struct containing two control registers `crl` and `crh`, and all the pins
  16. //! `px0..px15`. These structs are what you use to interract with the pins to change their modes,
  17. //! or their inputs or outputs. For example, to set `pa5` high, you would call
  18. //!
  19. //! ```rust
  20. //! let output = gpioa.pa5.into_push_pull_output(&mut gpioa.crl);
  21. //! output.set_high();
  22. //! ```
  23. //!
  24. //! Each GPIO pin can be set to various modes:
  25. //!
  26. //! - **Alternate**: Pin mode required when the pin is driven by other peripherals
  27. //! - **Dynamic**: Pin mode is selected at runtime. See changing configurations for more details
  28. //! - Input
  29. //! - **PullUp**: Input connected to high with a weak pull up resistor. Will be high when nothing
  30. //! is connected
  31. //! - **PullDown**: Input connected to high with a weak pull up resistor. Will be low when nothing
  32. //! is connected
  33. //! - **Floating**: Input not pulled to high or low. Will be undefined when nothing is connected
  34. //! - Output
  35. //! - **PushPull**: Output which either drives the pin high or low
  36. //! - **OpenDrain**: Output which leaves the gate floating, or pulls it do ground in drain
  37. //! mode. Can be used as an input in the `open` configuration
  38. //! - **Debugger**: Some pins start out being used by the debugger. A pin in this mode can only be
  39. //! used if the [JTAG peripheral has been turned off](#accessing-pa15-pb3-and-pb14).
  40. //!
  41. //! ## Changing modes
  42. //! The simplest way to change the pin mode is to use the `into_<mode>` functions. These return a
  43. //! new struct with the correct mode that you can use the input or output functions on.
  44. //!
  45. //! If you need a more temporary mode change, and can not use the `into_<mode>` functions for
  46. //! ownership reasons, you can use the `as_<mode>` functions to temporarily change the pin type, do
  47. //! some output or input, and then have it change back once done.
  48. //!
  49. //! ### Dynamic Mode Change
  50. //! The above mode change methods guarantee that you can only call input functions when the pin is
  51. //! in input mode, and output when in output modes, but can lead to some issues. Therefore, there
  52. //! is also a mode where the state is kept track of at runtime, allowing you to change the mode
  53. //! often, and without problems with ownership, or references, at the cost of some performance and
  54. //! the risk of runtime errors.
  55. //!
  56. //! To make a pin dynamic, use the `into_dynamic` function, and then use the `make_<mode>` functions to
  57. //! change the mode
  58. //!
  59. //! ## Accessing PA15, PB3, and PB14
  60. //!
  61. //! These pins are used by the JTAG peripheral by default. To use them in your program, you need to
  62. //! disable that peripheral. This is done using the [afio::MAPR::disable_jtag](../afio/struct.MAPR.html#method.disable_jtag) function
  63. //!
  64. //! # Interfacing with v1 traits
  65. //!
  66. //! `embedded-hal` has two versions of the digital traits, `v2` which is used by this crate and
  67. //! `v1` which is deprecated but still used by a lot of drivers. If you want to use such a driver
  68. //! with this crate, you need to convert the digital pins to the `v1` type.
  69. //!
  70. //! This is done using `embedded-hal::digital::v1_compat::OldOutputPin`. For example:
  71. //!
  72. //! ```rust
  73. //! let nss = gpioa.pa4.into_push_pull_output(&mut gpioa.crl);
  74. //! let mut mfrc522 = Mfrc522::new(spi, OldOutputPin::from(nss)).unwrap();
  75. //! ```
  76. use core::marker::PhantomData;
  77. use crate::afio;
  78. use crate::pac::EXTI;
  79. use crate::rcc::APB2;
  80. /// Slew rates available for Output and relevant AlternateMode Pins
  81. ///
  82. /// See Table 21 "Output MODE bits" in the reference
  83. pub enum IOPinSpeed {
  84. /// Slew at 10Mhz
  85. Mhz10 = 0b01, // (yes, this one is "less" then 2Mhz)
  86. /// Slew at 2Mhz
  87. Mhz2 = 0b10,
  88. /// Slew at 50Mhz
  89. Mhz50 = 0b11,
  90. }
  91. /// Allow setting of the slew rate of an IO pin
  92. ///
  93. /// Initially all pins are set to the maximum slew rate
  94. pub trait OutputSpeed<CR> {
  95. fn set_speed(&mut self, cr: &mut CR, speed: IOPinSpeed);
  96. }
  97. /// Extension trait to split a GPIO peripheral in independent pins and registers
  98. pub trait GpioExt {
  99. /// The to split the GPIO into
  100. type Parts;
  101. /// Splits the GPIO block into independent pins and registers
  102. fn split(self, apb2: &mut APB2) -> Self::Parts;
  103. }
  104. /// Marker trait for pin mode detection.
  105. pub trait Mode<MODE> {}
  106. /// Marker trait for active states.
  107. pub trait Active {}
  108. /// Input mode (type state)
  109. pub struct Input<MODE> {
  110. _mode: PhantomData<MODE>,
  111. }
  112. impl<MODE> Active for Input<MODE> {}
  113. /// Used by the debugger (type state)
  114. pub struct Debugger;
  115. /// Floating input (type state)
  116. pub struct Floating;
  117. /// Pulled down input (type state)
  118. pub struct PullDown;
  119. /// Pulled up input (type state)
  120. pub struct PullUp;
  121. /// Output mode (type state)
  122. pub struct Output<MODE> {
  123. _mode: PhantomData<MODE>,
  124. }
  125. impl<MODE> Active for Output<MODE> {}
  126. /// Push pull output (type state)
  127. pub struct PushPull;
  128. /// Open drain output (type state)
  129. pub struct OpenDrain;
  130. /// Analog mode (type state)
  131. pub struct Analog;
  132. impl Active for Analog {}
  133. /// Alternate function
  134. pub struct Alternate<MODE> {
  135. _mode: PhantomData<MODE>,
  136. }
  137. impl<MODE> Active for Alternate<MODE> {}
  138. pub enum State {
  139. High,
  140. Low,
  141. }
  142. // Using SCREAMING_SNAKE_CASE to be consistent with other HALs
  143. // see 59b2740 and #125 for motivation
  144. #[allow(non_camel_case_types)]
  145. #[derive(Debug, PartialEq)]
  146. pub enum Edge {
  147. RISING,
  148. FALLING,
  149. RISING_FALLING,
  150. }
  151. /// External Interrupt Pin
  152. pub trait ExtiPin {
  153. fn make_interrupt_source(&mut self, afio: &mut afio::Parts);
  154. fn trigger_on_edge(&mut self, exti: &EXTI, level: Edge);
  155. fn enable_interrupt(&mut self, exti: &EXTI);
  156. fn disable_interrupt(&mut self, exti: &EXTI);
  157. fn clear_interrupt_pending_bit(&mut self);
  158. fn check_interrupt(&mut self) -> bool;
  159. }
  160. /// Tracks the current pin state for dynamic pins
  161. pub enum Dynamic {
  162. InputFloating,
  163. InputPullUp,
  164. InputPullDown,
  165. OutputPushPull,
  166. OutputOpenDrain,
  167. }
  168. impl Active for Dynamic {}
  169. #[derive(Debug, PartialEq)]
  170. pub enum PinModeError {
  171. IncorrectMode,
  172. }
  173. impl Dynamic {
  174. fn is_input(&self) -> bool {
  175. use Dynamic::*;
  176. match self {
  177. InputFloating | InputPullUp | InputPullDown | OutputOpenDrain => true,
  178. OutputPushPull => false,
  179. }
  180. }
  181. fn is_output(&self) -> bool {
  182. use Dynamic::*;
  183. match self {
  184. InputFloating | InputPullUp | InputPullDown => false,
  185. OutputPushPull | OutputOpenDrain => true,
  186. }
  187. }
  188. }
  189. /// NOTE: This trait should ideally be private but must be pub in order to avoid
  190. /// complaints from the compiler.
  191. pub trait PinMode<CR> {
  192. unsafe fn set_mode(cr: &mut CR) -> Self;
  193. }
  194. // These impls are needed because a macro can not brace initialise a ty token
  195. impl<MODE> Input<MODE> {
  196. const fn _new() -> Self {
  197. Self { _mode: PhantomData }
  198. }
  199. }
  200. impl<MODE> Output<MODE> {
  201. const fn _new() -> Self {
  202. Self { _mode: PhantomData }
  203. }
  204. }
  205. impl<MODE> Alternate<MODE> {
  206. const fn _new() -> Self {
  207. Self { _mode: PhantomData }
  208. }
  209. }
  210. impl Debugger {
  211. const fn _new() -> Self {
  212. Self {}
  213. }
  214. }
  215. macro_rules! gpio {
  216. ($GPIOX:ident, $gpiox:ident, $gpioy:ident, $PXx:ident, $extigpionr:expr, [
  217. $($PXi:ident: ($pxi:ident, $i:expr, $MODE:ty, $CR:ident, $exticri:ident),)+
  218. ]) => {
  219. /// GPIO
  220. pub mod $gpiox {
  221. use core::convert::Infallible;
  222. use core::marker::PhantomData;
  223. use crate::hal::digital::v2::{InputPin, OutputPin, StatefulOutputPin, toggleable};
  224. use crate::pac::{$gpioy, $GPIOX};
  225. use crate::pac::EXTI;
  226. use crate::afio;
  227. use crate::rcc::{APB2, Enable, Reset};
  228. use super::{
  229. Alternate, Floating, GpioExt, Input,
  230. OpenDrain,
  231. Output,
  232. PullDown,
  233. PullUp,
  234. PushPull,
  235. Analog,
  236. State,
  237. Active,
  238. Debugger,
  239. Pxx,
  240. Mode,
  241. Edge,
  242. ExtiPin,
  243. PinMode,
  244. Dynamic,
  245. PinModeError,
  246. OutputSpeed,
  247. IOPinSpeed,
  248. };
  249. /// GPIO parts
  250. pub struct Parts {
  251. /// Opaque CRL register
  252. pub crl: CRL,
  253. /// Opaque CRH register
  254. pub crh: CRH,
  255. $(
  256. /// Pin
  257. pub $pxi: $PXi<$MODE>,
  258. )+
  259. }
  260. impl GpioExt for $GPIOX {
  261. type Parts = Parts;
  262. fn split(self, apb: &mut APB2) -> Parts {
  263. $GPIOX::enable(apb);
  264. $GPIOX::reset(apb);
  265. Parts {
  266. crl: CRL { _0: () },
  267. crh: CRH { _0: () },
  268. $(
  269. $pxi: $PXi { mode: <$MODE>::_new() },
  270. )+
  271. }
  272. }
  273. }
  274. /// Opaque CRL register
  275. pub struct CRL {
  276. _0: (),
  277. }
  278. impl CRL {
  279. // NOTE(allow) we get a warning on GPIOC because it only has 3 high pins
  280. #[allow(dead_code)]
  281. pub(crate) fn cr(&mut self) -> &$gpioy::CRL {
  282. unsafe { &(*$GPIOX::ptr()).crl }
  283. }
  284. }
  285. /// Opaque CRH register
  286. pub struct CRH {
  287. _0: (),
  288. }
  289. impl CRH {
  290. pub(crate) fn cr(&mut self) -> &$gpioy::CRH {
  291. unsafe { &(*$GPIOX::ptr()).crh }
  292. }
  293. }
  294. /// Partially erased pin. Only used in the Pxx enum
  295. pub struct Generic<MODE> {
  296. i: u8,
  297. _mode: PhantomData<MODE>,
  298. }
  299. impl<MODE> Generic<MODE> {
  300. pub fn downgrade(self) -> Pxx<MODE> {
  301. Pxx::$PXx(self)
  302. }
  303. }
  304. impl<MODE> OutputPin for Generic<Output<MODE>> {
  305. type Error = Infallible;
  306. fn set_high(&mut self) -> Result<(), Self::Error> {
  307. // NOTE(unsafe) atomic write to a stateless register
  308. Ok(unsafe { (*$GPIOX::ptr()).bsrr.write(|w| w.bits(1 << self.i)) })
  309. }
  310. fn set_low(&mut self) -> Result<(), Self::Error> {
  311. // NOTE(unsafe) atomic write to a stateless register
  312. Ok(unsafe { (*$GPIOX::ptr()).bsrr.write(|w| w.bits(1 << (16 + self.i))) })
  313. }
  314. }
  315. impl<MODE> InputPin for Generic<Input<MODE>> {
  316. type Error = Infallible;
  317. fn is_high(&self) -> Result<bool, Self::Error> {
  318. self.is_low().map(|b| !b)
  319. }
  320. fn is_low(&self) -> Result<bool, Self::Error> {
  321. // NOTE(unsafe) atomic read with no side effects
  322. Ok(unsafe { (*$GPIOX::ptr()).idr.read().bits() & (1 << self.i) == 0 })
  323. }
  324. }
  325. impl<MODE> ExtiPin for Generic<Input<MODE>> {
  326. /// Make corresponding EXTI line sensitive to this pin
  327. fn make_interrupt_source(&mut self, afio: &mut afio::Parts) {
  328. let offset = 4 * (self.i % 4);
  329. match self.i {
  330. 0..=3 => {
  331. afio.exticr1.exticr1().modify(|r, w| unsafe {
  332. w.bits((r.bits() & !(0xf << offset)) | ($extigpionr << offset))
  333. });
  334. },
  335. 4..=7 => {
  336. afio.exticr2.exticr2().modify(|r, w| unsafe {
  337. w.bits((r.bits() & !(0xf << offset)) | ($extigpionr << offset))
  338. });
  339. },
  340. 8..=11 => {
  341. afio.exticr3.exticr3().modify(|r, w| unsafe {
  342. w.bits((r.bits() & !(0xf << offset)) | ($extigpionr << offset))
  343. });
  344. },
  345. 12..=15 => {
  346. afio.exticr4.exticr4().modify(|r, w| unsafe {
  347. w.bits((r.bits() & !(0xf << offset)) | ($extigpionr << offset))
  348. });
  349. },
  350. _ => unreachable!(),
  351. }
  352. }
  353. /// Generate interrupt on rising edge, falling edge or both
  354. fn trigger_on_edge(&mut self, exti: &EXTI, edge: Edge) {
  355. match edge {
  356. Edge::RISING => {
  357. exti.rtsr.modify(|r, w| unsafe { w.bits(r.bits() | (1 << self.i)) });
  358. exti.ftsr.modify(|r, w| unsafe { w.bits(r.bits() & !(1 << self.i)) });
  359. },
  360. Edge::FALLING => {
  361. exti.ftsr.modify(|r, w| unsafe { w.bits(r.bits() | (1 << self.i)) });
  362. exti.rtsr.modify(|r, w| unsafe { w.bits(r.bits() & !(1 << self.i)) });
  363. },
  364. Edge::RISING_FALLING => {
  365. exti.rtsr.modify(|r, w| unsafe { w.bits(r.bits() | (1 << self.i)) });
  366. exti.ftsr.modify(|r, w| unsafe { w.bits(r.bits() | (1 << self.i)) });
  367. }
  368. }
  369. }
  370. /// Enable external interrupts from this pin.
  371. fn enable_interrupt(&mut self, exti: &EXTI) {
  372. exti.imr.modify(|r, w| unsafe { w.bits(r.bits() | (1 << self.i)) });
  373. }
  374. /// Disable external interrupts from this pin
  375. fn disable_interrupt(&mut self, exti: &EXTI) {
  376. exti.imr.modify(|r, w| unsafe { w.bits(r.bits() & !(1 << self.i)) });
  377. }
  378. /// Clear the interrupt pending bit for this pin
  379. fn clear_interrupt_pending_bit(&mut self) {
  380. unsafe { (*EXTI::ptr()).pr.write(|w| w.bits(1 << self.i) ) };
  381. }
  382. /// Reads the interrupt pending bit for this pin
  383. fn check_interrupt(&mut self) -> bool {
  384. unsafe { ((*EXTI::ptr()).pr.read().bits() & (1 << self.i)) != 0 }
  385. }
  386. }
  387. impl <MODE> StatefulOutputPin for Generic<Output<MODE>> {
  388. fn is_set_high(&self) -> Result<bool, Self::Error> {
  389. self.is_set_low().map(|b| !b)
  390. }
  391. fn is_set_low(&self) -> Result<bool, Self::Error> {
  392. // NOTE(unsafe) atomic read with no side effects
  393. Ok(unsafe { (*$GPIOX::ptr()).odr.read().bits() & (1 << self.i) == 0 })
  394. }
  395. }
  396. impl <MODE> toggleable::Default for Generic<Output<MODE>> {}
  397. impl InputPin for Generic<Output<OpenDrain>> {
  398. type Error = Infallible;
  399. fn is_high(&self) -> Result<bool, Self::Error> {
  400. self.is_low().map(|b| !b)
  401. }
  402. fn is_low(&self) -> Result<bool, Self::Error> {
  403. // NOTE(unsafe) atomic read with no side effects
  404. Ok(unsafe { (*$GPIOX::ptr()).idr.read().bits() & (1 << self.i) == 0 })
  405. }
  406. }
  407. pub type $PXx<MODE> = Pxx<MODE>;
  408. impl<MODE> Mode<MODE> for Generic<MODE> {}
  409. $(
  410. /// Pin
  411. pub struct $PXi<MODE> {
  412. mode: MODE,
  413. }
  414. impl<MODE> Mode<MODE> for $PXi<MODE> {}
  415. impl $PXi<Debugger> {
  416. /// Put the pin in an active state. The caller
  417. /// must enforce that the pin is really in this
  418. /// state in the hardware.
  419. #[allow(dead_code)]
  420. pub(crate) unsafe fn activate(self) -> $PXi<Input<Floating>> {
  421. $PXi { mode: Input::_new() }
  422. }
  423. }
  424. impl<MODE> $PXi<MODE> where MODE: Active {
  425. /// Configures the pin to operate as an alternate function push-pull output
  426. /// pin.
  427. #[inline]
  428. pub fn into_alternate_push_pull(
  429. self,
  430. cr: &mut $CR,
  431. ) -> $PXi<Alternate<PushPull>> {
  432. const OFFSET: u32 = (4 * $i) % 32;
  433. // Alternate function output push pull
  434. const CNF: u32 = 0b10;
  435. // Output mode, max speed 50 MHz
  436. const MODE: u32 = 0b11;
  437. const BITS: u32 = (CNF << 2) | MODE;
  438. // input mode
  439. cr
  440. .cr()
  441. .modify(|r, w| unsafe {
  442. w.bits((r.bits() & !(0b1111 << OFFSET)) | (BITS << OFFSET))
  443. });
  444. $PXi { mode: Alternate::_new() }
  445. }
  446. /// Configures the pin to operate as an alternate function open-drain output
  447. /// pin.
  448. #[inline]
  449. pub fn into_alternate_open_drain(
  450. self,
  451. cr: &mut $CR,
  452. ) -> $PXi<Alternate<OpenDrain>> {
  453. const OFFSET: u32 = (4 * $i) % 32;
  454. // Alternate function output open drain
  455. const CNF: u32 = 0b11;
  456. // Output mode, max speed 50 MHz
  457. const MODE: u32 = 0b11;
  458. const BITS: u32 = (CNF << 2) | MODE;
  459. // input mode
  460. cr
  461. .cr()
  462. .modify(|r, w| unsafe {
  463. w.bits((r.bits() & !(0b1111 << OFFSET)) | (BITS << OFFSET))
  464. });
  465. $PXi { mode: Alternate::_new() }
  466. }
  467. /// Configures the pin to operate as a floating input pin
  468. #[inline]
  469. pub fn into_floating_input(
  470. self,
  471. cr: &mut $CR,
  472. ) -> $PXi<Input<Floating>> {
  473. unsafe {
  474. $PXi::<Input<Floating>>::set_mode(cr)
  475. }
  476. }
  477. /// Configures the pin to operate as a pulled down input pin
  478. #[inline]
  479. pub fn into_pull_down_input(
  480. self,
  481. cr: &mut $CR,
  482. ) -> $PXi<Input<PullDown>> {
  483. unsafe {
  484. $PXi::<Input<PullDown>>::set_mode(cr)
  485. }
  486. }
  487. /// Configures the pin to operate as a pulled up input pin
  488. #[inline]
  489. pub fn into_pull_up_input(
  490. self,
  491. cr: &mut $CR,
  492. ) -> $PXi<Input<PullUp>> {
  493. unsafe {
  494. $PXi::<Input<PullUp>>::set_mode(cr)
  495. }
  496. }
  497. /// Configures the pin to operate as an open-drain output pin.
  498. /// Initial state will be low.
  499. #[inline]
  500. pub fn into_open_drain_output(
  501. self,
  502. cr: &mut $CR,
  503. ) -> $PXi<Output<OpenDrain>> {
  504. self.into_open_drain_output_with_state(cr, State::Low)
  505. }
  506. /// Configures the pin to operate as an open-drain output pin.
  507. /// `initial_state` specifies whether the pin should be initially high or low.
  508. #[inline]
  509. pub fn into_open_drain_output_with_state(
  510. mut self,
  511. cr: &mut $CR,
  512. initial_state: State,
  513. ) -> $PXi<Output<OpenDrain>> {
  514. self.set_state(initial_state);
  515. unsafe {
  516. $PXi::<Output<OpenDrain>>::set_mode(cr)
  517. }
  518. }
  519. /// Configures the pin to operate as an push-pull output pin.
  520. /// Initial state will be low.
  521. #[inline]
  522. pub fn into_push_pull_output(
  523. self,
  524. cr: &mut $CR,
  525. ) -> $PXi<Output<PushPull>> {
  526. self.into_push_pull_output_with_state(cr, State::Low)
  527. }
  528. /// Configures the pin to operate as an push-pull output pin.
  529. /// `initial_state` specifies whether the pin should be initially high or low.
  530. #[inline]
  531. pub fn into_push_pull_output_with_state(
  532. mut self,
  533. cr: &mut $CR,
  534. initial_state: State,
  535. ) -> $PXi<Output<PushPull>> {
  536. self.set_state(initial_state);
  537. unsafe {
  538. $PXi::<Output<PushPull>>::set_mode(cr)
  539. }
  540. }
  541. /// Configures the pin to operate as an analog input pin
  542. #[inline]
  543. pub fn into_analog(self, cr: &mut $CR) -> $PXi<Analog> {
  544. unsafe {
  545. $PXi::<Analog>::set_mode(cr)
  546. }
  547. }
  548. /// Configures the pin as a pin that can change between input
  549. /// and output without changing the type. It starts out
  550. /// as a floating input
  551. #[inline]
  552. pub fn into_dynamic(self, cr: &mut $CR) -> $PXi<Dynamic> {
  553. self.into_floating_input(cr);
  554. $PXi::<Dynamic>{mode: Dynamic::InputFloating}
  555. }
  556. }
  557. // These macros are defined here instead of at the top level in order
  558. // to be able to refer to macro variables from the outer layers.
  559. macro_rules! impl_temp_output {
  560. (
  561. $fn_name:ident,
  562. $stateful_fn_name:ident,
  563. $mode:ty
  564. ) => {
  565. /**
  566. Temporarily change the mode of the pin.
  567. The value of the pin after conversion is undefined. If you
  568. want to control it, use `$stateful_fn_name`
  569. */
  570. #[inline]
  571. pub fn $fn_name(
  572. &mut self,
  573. cr: &mut $CR,
  574. mut f: impl FnMut(&mut $PXi<$mode>)
  575. ) {
  576. let mut temp = unsafe { $PXi::<$mode>::set_mode(cr) };
  577. f(&mut temp);
  578. unsafe {
  579. Self::set_mode(cr);
  580. }
  581. }
  582. /**
  583. Temporarily change the mode of the pin.
  584. Note that the new state is set slightly before conversion
  585. happens. This can cause a short output glitch if switching
  586. between output modes
  587. */
  588. #[inline]
  589. pub fn $stateful_fn_name(
  590. &mut self,
  591. cr: &mut $CR,
  592. state: State,
  593. mut f: impl FnMut(&mut $PXi<$mode>)
  594. ) {
  595. self.set_state(state);
  596. let mut temp = unsafe { $PXi::<$mode>::set_mode(cr) };
  597. f(&mut temp);
  598. unsafe {
  599. Self::set_mode(cr);
  600. }
  601. }
  602. }
  603. }
  604. macro_rules! impl_temp_input {
  605. (
  606. $fn_name:ident,
  607. $mode:ty
  608. ) => {
  609. /**
  610. Temporarily change the mode of the pin.
  611. */
  612. #[inline]
  613. pub fn $fn_name(
  614. &mut self,
  615. cr: &mut $CR,
  616. mut f: impl FnMut(&mut $PXi<$mode>)
  617. ) {
  618. let mut temp = unsafe { $PXi::<$mode>::set_mode(cr) };
  619. f(&mut temp);
  620. unsafe {
  621. Self::set_mode(cr);
  622. }
  623. }
  624. }
  625. }
  626. impl<MODE> $PXi<MODE> where MODE: Active, $PXi<MODE>: PinMode<$CR> {
  627. impl_temp_output!(
  628. as_push_pull_output,
  629. as_push_pull_output_with_state,
  630. Output<PushPull>
  631. );
  632. impl_temp_output!(
  633. as_open_drain_output,
  634. as_open_drain_output_with_state,
  635. Output<OpenDrain>
  636. );
  637. impl_temp_input!(
  638. as_floating_input,
  639. Input<Floating>
  640. );
  641. impl_temp_input!(
  642. as_pull_up_input,
  643. Input<PullUp>
  644. );
  645. impl_temp_input!(
  646. as_pull_down_input,
  647. Input<PullDown>
  648. );
  649. }
  650. impl<MODE> $PXi<MODE> where MODE: Active {
  651. /// Erases the pin number from the type
  652. #[inline]
  653. fn into_generic(self) -> Generic<MODE> {
  654. Generic {
  655. i: $i,
  656. _mode: PhantomData,
  657. }
  658. }
  659. /// Erases the pin number and port from the type
  660. ///
  661. /// This is useful when you want to collect the pins into an array where you
  662. /// need all the elements to have the same type
  663. pub fn downgrade(self) -> Pxx<MODE> {
  664. self.into_generic().downgrade()
  665. }
  666. }
  667. // embedded_hal impls
  668. impl<MODE> OutputPin for $PXi<Output<MODE>> {
  669. type Error = Infallible;
  670. #[inline]
  671. fn set_high(&mut self) -> Result<(), Self::Error> {
  672. // NOTE(unsafe) atomic write to a stateless register
  673. Ok(self.set_state(State::High))
  674. }
  675. #[inline]
  676. fn set_low(&mut self) -> Result<(), Self::Error> {
  677. // NOTE(unsafe) atomic write to a stateless register
  678. Ok(self.set_state(State::Low))
  679. }
  680. }
  681. impl<MODE> StatefulOutputPin for $PXi<Output<MODE>> {
  682. #[inline]
  683. fn is_set_high(&self) -> Result<bool, Self::Error> {
  684. self.is_set_low().map(|b| !b)
  685. }
  686. #[inline]
  687. fn is_set_low(&self) -> Result<bool, Self::Error> {
  688. Ok(self._is_set_low())
  689. }
  690. }
  691. impl<MODE> OutputSpeed<$CR> for $PXi<Output<MODE>> {
  692. fn set_speed(&mut self, cr: &mut $CR, speed: IOPinSpeed){
  693. const OFFSET: u32 = (4 * $i) % 32;
  694. cr.cr().modify(|r, w| unsafe {
  695. w.bits((r.bits() & !(0b11 << OFFSET)) | ((speed as u32) << OFFSET))
  696. });
  697. }
  698. }
  699. impl OutputSpeed<$CR> for $PXi<Alternate<PushPull>> {
  700. fn set_speed(&mut self, cr: &mut $CR, speed: IOPinSpeed){
  701. const OFFSET: u32 = (4 * $i) % 32;
  702. cr.cr().modify(|r, w| unsafe {
  703. w.bits((r.bits() & !(0b11 << OFFSET)) | ((speed as u32) << OFFSET))
  704. });
  705. }
  706. }
  707. impl<MODE> toggleable::Default for $PXi<Output<MODE>> {}
  708. impl<MODE> InputPin for $PXi<Input<MODE>> {
  709. type Error = Infallible;
  710. #[inline]
  711. fn is_high(&self) -> Result<bool, Self::Error> {
  712. self.is_low().map(|b| !b)
  713. }
  714. #[inline]
  715. fn is_low(&self) -> Result<bool, Self::Error> {
  716. // NOTE(unsafe) atomic read with no side effects
  717. Ok(self._is_low())
  718. }
  719. }
  720. impl InputPin for $PXi<Output<OpenDrain>> {
  721. type Error = Infallible;
  722. #[inline]
  723. fn is_high(&self) -> Result<bool, Self::Error> {
  724. self.is_low().map(|b| !b)
  725. }
  726. #[inline]
  727. fn is_low(&self) -> Result<bool, Self::Error> {
  728. Ok(self._is_low())
  729. }
  730. }
  731. // Dynamic pin
  732. impl $PXi<Dynamic> {
  733. #[inline]
  734. pub fn make_pull_up_input(&mut self, cr: &mut $CR) {
  735. // NOTE(unsafe), we have a mutable reference to the current pin
  736. unsafe { $PXi::<Input<PullUp>>::set_mode(cr) };
  737. self.mode = Dynamic::InputPullUp;
  738. }
  739. #[inline]
  740. pub fn make_pull_down_input(&mut self, cr: &mut $CR) {
  741. // NOTE(unsafe), we have a mutable reference to the current pin
  742. unsafe { $PXi::<Input<PullDown>>::set_mode(cr) };
  743. self.mode = Dynamic::InputPullDown;
  744. }
  745. #[inline]
  746. pub fn make_floating_input(&mut self, cr: &mut $CR) {
  747. // NOTE(unsafe), we have a mutable reference to the current pin
  748. unsafe { $PXi::<Input<Floating>>::set_mode(cr) };
  749. self.mode = Dynamic::InputFloating;
  750. }
  751. #[inline]
  752. pub fn make_push_pull_output(&mut self, cr: &mut $CR) {
  753. // NOTE(unsafe), we have a mutable reference to the current pin
  754. unsafe { $PXi::<Output<PushPull>>::set_mode(cr) };
  755. self.mode = Dynamic::OutputPushPull;
  756. }
  757. #[inline]
  758. pub fn make_open_drain_output(&mut self, cr: &mut $CR) {
  759. // NOTE(unsafe), we have a mutable reference to the current pin
  760. unsafe { $PXi::<Output<OpenDrain>>::set_mode(cr) };
  761. self.mode = Dynamic::OutputOpenDrain;
  762. }
  763. }
  764. impl OutputPin for $PXi<Dynamic> {
  765. type Error = PinModeError;
  766. fn set_high(&mut self) -> Result<(), Self::Error> {
  767. if self.mode.is_output() {
  768. self.set_state(State::High);
  769. Ok(())
  770. }
  771. else {
  772. Err(PinModeError::IncorrectMode)
  773. }
  774. }
  775. fn set_low(&mut self) -> Result<(), Self::Error> {
  776. if self.mode.is_output() {
  777. self.set_state(State::Low);
  778. Ok(())
  779. }
  780. else {
  781. Err(PinModeError::IncorrectMode)
  782. }
  783. }
  784. }
  785. impl InputPin for $PXi<Dynamic> {
  786. type Error = PinModeError;
  787. fn is_high(&self) -> Result<bool, Self::Error> {
  788. self.is_low().map(|b| !b)
  789. }
  790. fn is_low(&self) -> Result<bool, Self::Error> {
  791. if self.mode.is_input() {
  792. Ok(self._is_low())
  793. }
  794. else {
  795. Err(PinModeError::IncorrectMode)
  796. }
  797. }
  798. }
  799. // Exti pin impls
  800. impl<MODE> ExtiPin for $PXi<Input<MODE>> {
  801. /// Configure EXTI Line $i to trigger from this pin.
  802. fn make_interrupt_source(&mut self, afio: &mut afio::Parts) {
  803. let offset = 4 * ($i % 4);
  804. afio.$exticri.$exticri().modify(|r, w| unsafe {
  805. let mut exticr = r.bits();
  806. exticr = (exticr & !(0xf << offset)) | ($extigpionr << offset);
  807. w.bits(exticr)
  808. });
  809. }
  810. /// Generate interrupt on rising edge, falling edge or both
  811. fn trigger_on_edge(&mut self, exti: &EXTI, edge: Edge) {
  812. match edge {
  813. Edge::RISING => {
  814. exti.rtsr.modify(|r, w| unsafe { w.bits(r.bits() | (1 << $i)) });
  815. exti.ftsr.modify(|r, w| unsafe { w.bits(r.bits() & !(1 << $i)) });
  816. },
  817. Edge::FALLING => {
  818. exti.ftsr.modify(|r, w| unsafe { w.bits(r.bits() | (1 << $i)) });
  819. exti.rtsr.modify(|r, w| unsafe { w.bits(r.bits() & !(1 << $i)) });
  820. },
  821. Edge::RISING_FALLING => {
  822. exti.rtsr.modify(|r, w| unsafe { w.bits(r.bits() | (1 << $i)) });
  823. exti.ftsr.modify(|r, w| unsafe { w.bits(r.bits() | (1 << $i)) });
  824. }
  825. }
  826. }
  827. /// Enable external interrupts from this pin.
  828. #[inline]
  829. fn enable_interrupt(&mut self, exti: &EXTI) {
  830. exti.imr.modify(|r, w| unsafe { w.bits(r.bits() | (1 << $i)) });
  831. }
  832. /// Disable external interrupts from this pin
  833. #[inline]
  834. fn disable_interrupt(&mut self, exti: &EXTI) {
  835. exti.imr.modify(|r, w| unsafe { w.bits(r.bits() & !(1 << $i)) });
  836. }
  837. /// Clear the interrupt pending bit for this pin
  838. #[inline]
  839. fn clear_interrupt_pending_bit(&mut self) {
  840. unsafe { (*EXTI::ptr()).pr.write(|w| w.bits(1 << $i) ) };
  841. }
  842. /// Reads the interrupt pending bit for this pin
  843. #[inline]
  844. fn check_interrupt(&mut self) -> bool {
  845. unsafe { ((*EXTI::ptr()).pr.read().bits() & (1 << $i)) != 0 }
  846. }
  847. }
  848. // Internal helper functions
  849. // NOTE: The functions in this impl block are "safe", but they
  850. // are callable when the pin is in modes where they don't make
  851. // sense.
  852. impl<MODE> $PXi<MODE> {
  853. /**
  854. Set the output of the pin regardless of its mode.
  855. Primarily used to set the output value of the pin
  856. before changing its mode to an output to avoid
  857. a short spike of an incorrect value
  858. */
  859. fn set_state(&mut self, state: State) {
  860. match state {
  861. State::High => unsafe {
  862. (*$GPIOX::ptr()).bsrr.write(|w| w.bits(1 << $i))
  863. }
  864. State::Low => unsafe {
  865. (*$GPIOX::ptr()).bsrr.write(|w| w.bits(1 << (16 + $i)))
  866. }
  867. }
  868. }
  869. fn _is_set_low(&self) -> bool {
  870. unsafe { (*$GPIOX::ptr()).odr.read().bits() & (1 << $i) == 0 }
  871. }
  872. fn _is_low(&self) -> bool {
  873. // NOTE(unsafe) atomic read with no side effects
  874. unsafe { (*$GPIOX::ptr()).idr.read().bits() & (1 << $i) == 0 }
  875. }
  876. }
  877. impl PinMode<$CR> for $PXi<Input<Floating>> {
  878. unsafe fn set_mode(cr: &mut $CR) -> Self {
  879. const OFFSET: u32 = (4 * $i) % 32;
  880. // Floating input
  881. const CNF: u32 = 0b01;
  882. // Input mode
  883. const MODE: u32 = 0b00;
  884. const BITS: u32 = (CNF << 2) | MODE;
  885. // input mode
  886. cr
  887. .cr()
  888. .modify(|r, w| {
  889. w.bits((r.bits() & !(0b1111 << OFFSET)) | (BITS << OFFSET))
  890. });
  891. $PXi { mode: Input::_new() }
  892. }
  893. }
  894. impl PinMode<$CR> for $PXi<Input<PullDown>> {
  895. unsafe fn set_mode(cr: &mut $CR) -> Self {
  896. const OFFSET: u32 = (4 * $i) % 32;
  897. // Pull up/down input
  898. const CNF: u32 = 0b10;
  899. // Input mode
  900. const MODE: u32 = 0b00;
  901. const BITS: u32 = (CNF << 2) | MODE;
  902. //pull down:
  903. // NOTE(unsafe) atomic write to a stateless register
  904. (*$GPIOX::ptr()).bsrr.write(|w| w.bits(1 << (16 + $i)));
  905. // input mode
  906. cr
  907. .cr()
  908. .modify(|r, w| {
  909. w.bits((r.bits() & !(0b1111 << OFFSET)) | (BITS << OFFSET))
  910. });
  911. $PXi { mode: Input::_new() }
  912. }
  913. }
  914. impl PinMode<$CR> for $PXi<Input<PullUp>> {
  915. unsafe fn set_mode(cr: &mut $CR) -> Self {
  916. const OFFSET: u32 = (4 * $i) % 32;
  917. // Pull up/down input
  918. const CNF: u32 = 0b10;
  919. // Input mode
  920. const MODE: u32 = 0b00;
  921. const BITS: u32 = (CNF << 2) | MODE;
  922. //pull up:
  923. // NOTE(unsafe) atomic write to a stateless register
  924. (*$GPIOX::ptr()).bsrr.write(|w| w.bits(1 << $i));
  925. // input mode
  926. cr
  927. .cr()
  928. .modify(|r, w| {
  929. w.bits((r.bits() & !(0b1111 << OFFSET)) | (BITS << OFFSET))
  930. });
  931. $PXi { mode: Input::_new() }
  932. }
  933. }
  934. impl PinMode<$CR> for $PXi<Output<OpenDrain>> {
  935. unsafe fn set_mode(cr: &mut $CR) -> Self {
  936. const OFFSET: u32 = (4 * $i) % 32;
  937. // General purpose output open-drain
  938. const CNF: u32 = 0b01;
  939. // Open-Drain Output mode, max speed 50 MHz
  940. const MODE: u32 = 0b11;
  941. const BITS: u32 = (CNF << 2) | MODE;
  942. cr
  943. .cr()
  944. .modify(|r, w| {
  945. w.bits((r.bits() & !(0b1111 << OFFSET)) | (BITS << OFFSET))
  946. });
  947. $PXi { mode: Output::_new() }
  948. }
  949. }
  950. impl PinMode<$CR> for $PXi<Output<PushPull>> {
  951. unsafe fn set_mode(cr: &mut $CR) -> Self {
  952. const OFFSET: u32 = (4 * $i) % 32;
  953. // General purpose output push-pull
  954. const CNF: u32 = 0b00;
  955. // Output mode, max speed 50 MHz
  956. const MODE: u32 = 0b11;
  957. const BITS: u32 = (CNF << 2) | MODE;
  958. cr
  959. .cr()
  960. .modify(|r, w| {
  961. w.bits((r.bits() & !(0b1111 << OFFSET)) | (BITS << OFFSET))
  962. });
  963. $PXi { mode: Output::_new() }
  964. }
  965. }
  966. impl PinMode<$CR> for $PXi<Analog> {
  967. unsafe fn set_mode(cr: &mut $CR) -> Self {
  968. const OFFSET: u32 = (4 * $i) % 32;
  969. // Analog input
  970. const CNF: u32 = 0b00;
  971. // Input mode
  972. const MODE: u32 = 0b00;
  973. const BITS: u32 = (CNF << 2) | MODE;
  974. // analog mode
  975. cr
  976. .cr()
  977. .modify(|r, w| {
  978. w.bits((r.bits() & !(0b1111 << OFFSET)) | (BITS << OFFSET))
  979. });
  980. $PXi { mode: Analog{} }
  981. }
  982. }
  983. )+
  984. }
  985. }
  986. }
  987. macro_rules! impl_pxx {
  988. ($(($port:ident :: $pin:ident)),*) => {
  989. use embedded_hal::digital::v2::{InputPin, StatefulOutputPin, OutputPin};
  990. use core::convert::Infallible;
  991. pub enum Pxx<MODE> {
  992. $(
  993. $pin($port::Generic<MODE>)
  994. ),*
  995. }
  996. impl<MODE> OutputPin for Pxx<Output<MODE>> {
  997. type Error = Infallible;
  998. fn set_high(&mut self) -> Result<(), Infallible> {
  999. match self {
  1000. $(Pxx::$pin(pin) => pin.set_high()),*
  1001. }
  1002. }
  1003. fn set_low(&mut self) -> Result<(), Infallible> {
  1004. match self {
  1005. $(Pxx::$pin(pin) => pin.set_low()),*
  1006. }
  1007. }
  1008. }
  1009. impl<MODE> StatefulOutputPin for Pxx<Output<MODE>> {
  1010. fn is_set_high(&self) -> Result<bool, Self::Error> {
  1011. match self {
  1012. $(Pxx::$pin(pin) => pin.is_set_high()),*
  1013. }
  1014. }
  1015. fn is_set_low(&self) -> Result<bool, Self::Error> {
  1016. match self {
  1017. $(Pxx::$pin(pin) => pin.is_set_low()),*
  1018. }
  1019. }
  1020. }
  1021. impl<MODE> InputPin for Pxx<Input<MODE>> {
  1022. type Error = Infallible;
  1023. fn is_high(&self) -> Result<bool, Infallible> {
  1024. match self {
  1025. $(Pxx::$pin(pin) => pin.is_high()),*
  1026. }
  1027. }
  1028. fn is_low(&self) -> Result<bool, Infallible> {
  1029. match self {
  1030. $(Pxx::$pin(pin) => pin.is_low()),*
  1031. }
  1032. }
  1033. }
  1034. impl InputPin for Pxx<Output<OpenDrain>> {
  1035. type Error = Infallible;
  1036. fn is_high(&self) -> Result<bool, Infallible> {
  1037. match self {
  1038. $(Pxx::$pin(pin) => pin.is_high()),*
  1039. }
  1040. }
  1041. fn is_low(&self) -> Result<bool, Infallible> {
  1042. match self {
  1043. $(Pxx::$pin(pin) => pin.is_low()),*
  1044. }
  1045. }
  1046. }
  1047. impl<MODE> ExtiPin for Pxx<Input<MODE>> {
  1048. fn make_interrupt_source(&mut self, afio: &mut afio::Parts) {
  1049. match self {
  1050. $(Pxx::$pin(pin) => pin.make_interrupt_source(afio)),*
  1051. }
  1052. }
  1053. fn trigger_on_edge(&mut self, exti: &EXTI, level: Edge) {
  1054. match self {
  1055. $(Pxx::$pin(pin) => pin.trigger_on_edge(exti, level)),*
  1056. }
  1057. }
  1058. fn enable_interrupt(&mut self, exti: &EXTI) {
  1059. match self {
  1060. $(Pxx::$pin(pin) => pin.enable_interrupt(exti)),*
  1061. }
  1062. }
  1063. fn disable_interrupt(&mut self, exti: &EXTI) {
  1064. match self {
  1065. $(Pxx::$pin(pin) => pin.disable_interrupt(exti)),*
  1066. }
  1067. }
  1068. fn clear_interrupt_pending_bit(&mut self) {
  1069. match self {
  1070. $(Pxx::$pin(pin) => pin.clear_interrupt_pending_bit()),*
  1071. }
  1072. }
  1073. fn check_interrupt(&mut self) -> bool {
  1074. match self {
  1075. $(Pxx::$pin(pin) => pin.check_interrupt()),*
  1076. }
  1077. }
  1078. }
  1079. }
  1080. }
  1081. impl_pxx! {
  1082. (gpioa::PAx),
  1083. (gpiob::PBx),
  1084. (gpioc::PCx),
  1085. (gpiod::PDx),
  1086. (gpioe::PEx),
  1087. (gpiof::PFx),
  1088. (gpiog::PGx)
  1089. }
  1090. gpio!(GPIOA, gpioa, gpioa, PAx, 0, [
  1091. PA0: (pa0, 0, Input<Floating>, CRL, exticr1),
  1092. PA1: (pa1, 1, Input<Floating>, CRL, exticr1),
  1093. PA2: (pa2, 2, Input<Floating>, CRL, exticr1),
  1094. PA3: (pa3, 3, Input<Floating>, CRL, exticr1),
  1095. PA4: (pa4, 4, Input<Floating>, CRL, exticr2),
  1096. PA5: (pa5, 5, Input<Floating>, CRL, exticr2),
  1097. PA6: (pa6, 6, Input<Floating>, CRL, exticr2),
  1098. PA7: (pa7, 7, Input<Floating>, CRL, exticr2),
  1099. PA8: (pa8, 8, Input<Floating>, CRH, exticr3),
  1100. PA9: (pa9, 9, Input<Floating>, CRH, exticr3),
  1101. PA10: (pa10, 10, Input<Floating>, CRH, exticr3),
  1102. PA11: (pa11, 11, Input<Floating>, CRH, exticr3),
  1103. PA12: (pa12, 12, Input<Floating>, CRH, exticr4),
  1104. PA13: (pa13, 13, Debugger, CRH, exticr4),
  1105. PA14: (pa14, 14, Debugger, CRH, exticr4),
  1106. PA15: (pa15, 15, Debugger, CRH, exticr4),
  1107. ]);
  1108. gpio!(GPIOB, gpiob, gpioa, PBx, 1, [
  1109. PB0: (pb0, 0, Input<Floating>, CRL, exticr1),
  1110. PB1: (pb1, 1, Input<Floating>, CRL, exticr1),
  1111. PB2: (pb2, 2, Input<Floating>, CRL, exticr1),
  1112. PB3: (pb3, 3, Debugger, CRL, exticr1),
  1113. PB4: (pb4, 4, Debugger, CRL, exticr2),
  1114. PB5: (pb5, 5, Input<Floating>, CRL, exticr2),
  1115. PB6: (pb6, 6, Input<Floating>, CRL, exticr2),
  1116. PB7: (pb7, 7, Input<Floating>, CRL, exticr2),
  1117. PB8: (pb8, 8, Input<Floating>, CRH, exticr3),
  1118. PB9: (pb9, 9, Input<Floating>, CRH, exticr3),
  1119. PB10: (pb10, 10, Input<Floating>, CRH, exticr3),
  1120. PB11: (pb11, 11, Input<Floating>, CRH, exticr3),
  1121. PB12: (pb12, 12, Input<Floating>, CRH, exticr4),
  1122. PB13: (pb13, 13, Input<Floating>, CRH, exticr4),
  1123. PB14: (pb14, 14, Input<Floating>, CRH, exticr4),
  1124. PB15: (pb15, 15, Input<Floating>, CRH, exticr4),
  1125. ]);
  1126. gpio!(GPIOC, gpioc, gpioa, PCx, 2, [
  1127. PC0: (pc0, 0, Input<Floating>, CRL, exticr1),
  1128. PC1: (pc1, 1, Input<Floating>, CRL, exticr1),
  1129. PC2: (pc2, 2, Input<Floating>, CRL, exticr1),
  1130. PC3: (pc3, 3, Input<Floating>, CRL, exticr1),
  1131. PC4: (pc4, 4, Input<Floating>, CRL, exticr2),
  1132. PC5: (pc5, 5, Input<Floating>, CRL, exticr2),
  1133. PC6: (pc6, 6, Input<Floating>, CRL, exticr2),
  1134. PC7: (pc7, 7, Input<Floating>, CRL, exticr2),
  1135. PC8: (pc8, 8, Input<Floating>, CRH, exticr3),
  1136. PC9: (pc9, 9, Input<Floating>, CRH, exticr3),
  1137. PC10: (pc10, 10, Input<Floating>, CRH, exticr3),
  1138. PC11: (pc11, 11, Input<Floating>, CRH, exticr3),
  1139. PC12: (pc12, 12, Input<Floating>, CRH, exticr4),
  1140. PC13: (pc13, 13, Input<Floating>, CRH, exticr4),
  1141. PC14: (pc14, 14, Input<Floating>, CRH, exticr4),
  1142. PC15: (pc15, 15, Input<Floating>, CRH, exticr4),
  1143. ]);
  1144. gpio!(GPIOD, gpiod, gpioa, PDx, 3, [
  1145. PD0: (pd0, 0, Input<Floating>, CRL, exticr1),
  1146. PD1: (pd1, 1, Input<Floating>, CRL, exticr1),
  1147. PD2: (pd2, 2, Input<Floating>, CRL, exticr1),
  1148. PD3: (pd3, 3, Input<Floating>, CRL, exticr1),
  1149. PD4: (pd4, 4, Input<Floating>, CRL, exticr2),
  1150. PD5: (pd5, 5, Input<Floating>, CRL, exticr2),
  1151. PD6: (pd6, 6, Input<Floating>, CRL, exticr2),
  1152. PD7: (pd7, 7, Input<Floating>, CRL, exticr2),
  1153. PD8: (pd8, 8, Input<Floating>, CRH, exticr3),
  1154. PD9: (pd9, 9, Input<Floating>, CRH, exticr3),
  1155. PD10: (pd10, 10, Input<Floating>, CRH, exticr3),
  1156. PD11: (pd11, 11, Input<Floating>, CRH, exticr3),
  1157. PD12: (pd12, 12, Input<Floating>, CRH, exticr4),
  1158. PD13: (pd13, 13, Input<Floating>, CRH, exticr4),
  1159. PD14: (pd14, 14, Input<Floating>, CRH, exticr4),
  1160. PD15: (pd15, 15, Input<Floating>, CRH, exticr4),
  1161. ]);
  1162. gpio!(GPIOE, gpioe, gpioa, PEx, 4, [
  1163. PE0: (pe0, 0, Input<Floating>, CRL, exticr1),
  1164. PE1: (pe1, 1, Input<Floating>, CRL, exticr1),
  1165. PE2: (pe2, 2, Input<Floating>, CRL, exticr1),
  1166. PE3: (pe3, 3, Input<Floating>, CRL, exticr1),
  1167. PE4: (pe4, 4, Input<Floating>, CRL, exticr2),
  1168. PE5: (pe5, 5, Input<Floating>, CRL, exticr2),
  1169. PE6: (pe6, 6, Input<Floating>, CRL, exticr2),
  1170. PE7: (pe7, 7, Input<Floating>, CRL, exticr2),
  1171. PE8: (pe8, 8, Input<Floating>, CRH, exticr3),
  1172. PE9: (pe9, 9, Input<Floating>, CRH, exticr3),
  1173. PE10: (pe10, 10, Input<Floating>, CRH, exticr3),
  1174. PE11: (pe11, 11, Input<Floating>, CRH, exticr3),
  1175. PE12: (pe12, 12, Input<Floating>, CRH, exticr4),
  1176. PE13: (pe13, 13, Input<Floating>, CRH, exticr4),
  1177. PE14: (pe14, 14, Input<Floating>, CRH, exticr4),
  1178. PE15: (pe15, 15, Input<Floating>, CRH, exticr4),
  1179. ]);
  1180. gpio!(GPIOF, gpiof, gpioa, PFx, 5, [
  1181. PF0: (pf0, 0, Input<Floating>, CRL, exticr1),
  1182. PF1: (pf1, 1, Input<Floating>, CRL, exticr1),
  1183. PF2: (pf2, 2, Input<Floating>, CRL, exticr1),
  1184. PF3: (pf3, 3, Input<Floating>, CRL, exticr1),
  1185. PF4: (pf4, 4, Input<Floating>, CRL, exticr2),
  1186. PF5: (pf5, 5, Input<Floating>, CRL, exticr2),
  1187. PF6: (pf6, 6, Input<Floating>, CRL, exticr2),
  1188. PF7: (pf7, 7, Input<Floating>, CRL, exticr2),
  1189. PF8: (pf8, 8, Input<Floating>, CRH, exticr3),
  1190. PF9: (pf9, 9, Input<Floating>, CRH, exticr3),
  1191. PF10: (pf10, 10, Input<Floating>, CRH, exticr3),
  1192. PF11: (pf11, 11, Input<Floating>, CRH, exticr3),
  1193. PF12: (pf12, 12, Input<Floating>, CRH, exticr4),
  1194. PF13: (pf13, 13, Input<Floating>, CRH, exticr4),
  1195. PF14: (pf14, 14, Input<Floating>, CRH, exticr4),
  1196. PF15: (pf15, 15, Input<Floating>, CRH, exticr4),
  1197. ]);
  1198. gpio!(GPIOG, gpiog, gpioa, PGx, 6, [
  1199. PG0: (pg0, 0, Input<Floating>, CRL, exticr1),
  1200. PG1: (pg1, 1, Input<Floating>, CRL, exticr1),
  1201. PG2: (pg2, 2, Input<Floating>, CRL, exticr1),
  1202. PG3: (pg3, 3, Input<Floating>, CRL, exticr1),
  1203. PG4: (pg4, 4, Input<Floating>, CRL, exticr2),
  1204. PG5: (pg5, 5, Input<Floating>, CRL, exticr2),
  1205. PG6: (pg6, 6, Input<Floating>, CRL, exticr2),
  1206. PG7: (pg7, 7, Input<Floating>, CRL, exticr2),
  1207. PG8: (pg8, 8, Input<Floating>, CRH, exticr3),
  1208. PG9: (pg9, 9, Input<Floating>, CRH, exticr3),
  1209. PG10: (pg10, 10, Input<Floating>, CRH, exticr3),
  1210. PG11: (pg11, 11, Input<Floating>, CRH, exticr3),
  1211. PG12: (pg12, 12, Input<Floating>, CRH, exticr4),
  1212. PG13: (pg13, 13, Input<Floating>, CRH, exticr4),
  1213. PG14: (pg14, 14, Input<Floating>, CRH, exticr4),
  1214. PG15: (pg15, 15, Input<Floating>, CRH, exticr4),
  1215. ]);