|
2 | 2 | //!
|
3 | 3 | //! For convenience, this module reexports the EXTI peripheral from the PAC.
|
4 | 4 |
|
5 |
| -pub mod line; |
6 |
| - |
7 |
| -use self::line::{ExtiLine, GpioLine, ConfigurableLine, DirectLine}; |
8 |
| - |
9 |
| -use crate::gpio; |
| 5 | +use crate::{gpio, pac}; |
10 | 6 | use crate::pwr::PowerMode;
|
11 | 7 | use crate::syscfg::SYSCFG;
|
12 | 8 |
|
@@ -243,3 +239,153 @@ impl ExtiExt for EXTI {
|
243 | 239 | });
|
244 | 240 | }
|
245 | 241 | }
|
| 242 | + |
| 243 | +mod sealed { |
| 244 | + pub trait Sealed {} |
| 245 | + |
| 246 | + impl Sealed for super::GpioLine {} |
| 247 | + impl Sealed for super::ConfigurableLine {} |
| 248 | + impl Sealed for super::DirectLine {} |
| 249 | +} |
| 250 | + |
| 251 | +/// Trait implemented by all types representing EXTI interrupt lines. |
| 252 | +pub trait ExtiLine: Sized + sealed::Sealed { |
| 253 | + /// Returns the line object corresponding to a raw EXTI line number. |
| 254 | + /// |
| 255 | + /// If `raw` is not a valid line for type `Self`, `None` is returned. |
| 256 | + fn from_raw_line(raw: u8) -> Option<Self>; |
| 257 | + |
| 258 | + /// Returns that raw EXTI line number corresponding to `self`. |
| 259 | + fn raw_line(&self) -> u8; |
| 260 | + |
| 261 | + /// Returns the NVIC interrupt corresponding to `self`. |
| 262 | + fn interrupt(&self) -> pac::Interrupt; |
| 263 | +} |
| 264 | + |
| 265 | +/// An EXTI interrupt line sourced by a GPIO. |
| 266 | +/// |
| 267 | +/// All `GpioLine`s are *configurable*: They can be configured to listen for |
| 268 | +/// rising or falling edges. |
| 269 | +#[derive(Copy, Clone, PartialEq, Eq)] |
| 270 | +pub struct GpioLine(u8); |
| 271 | + |
| 272 | +impl ExtiLine for GpioLine { |
| 273 | + fn from_raw_line(line: u8) -> Option<Self> { |
| 274 | + match line { |
| 275 | + 0..=15 => Some(GpioLine(line)), |
| 276 | + _ => None, |
| 277 | + } |
| 278 | + } |
| 279 | + |
| 280 | + fn raw_line(&self) -> u8 { |
| 281 | + self.0 |
| 282 | + } |
| 283 | + |
| 284 | + fn interrupt(&self) -> pac::Interrupt { |
| 285 | + use pac::Interrupt::*; |
| 286 | + match self.0 { |
| 287 | + 0..=1 => EXTI0_1, |
| 288 | + 2..=3 => EXTI2_3, |
| 289 | + _ => EXTI4_15, |
| 290 | + } |
| 291 | + } |
| 292 | +} |
| 293 | + |
| 294 | +/// A configurable EXTI line that is not a GPIO-sourced line. |
| 295 | +/// |
| 296 | +/// These lines can be configured to listen for rising edges, falling edges, or |
| 297 | +/// both. |
| 298 | +#[derive(Copy, Clone, PartialEq, Eq)] |
| 299 | +pub enum ConfigurableLine { |
| 300 | + Pvd = 16, |
| 301 | + RtcAlarm = 17, |
| 302 | + RtcTamper_CssLse = 19, |
| 303 | + RtcWakeup = 20, |
| 304 | + Comp1 = 21, |
| 305 | + Comp2 = 22, |
| 306 | +} |
| 307 | + |
| 308 | +impl ExtiLine for ConfigurableLine { |
| 309 | + fn from_raw_line(line: u8) -> Option<Self> { |
| 310 | + use ConfigurableLine::*; |
| 311 | + |
| 312 | + Some(match line { |
| 313 | + 16 => Pvd, |
| 314 | + 17 => RtcAlarm, |
| 315 | + // 18 = USB (or reserved) |
| 316 | + 19 => RtcTamper_CssLse, |
| 317 | + 20 => RtcWakeup, |
| 318 | + 21 => Comp1, |
| 319 | + 22 => Comp2, |
| 320 | + _ => return None, |
| 321 | + }) |
| 322 | + } |
| 323 | + |
| 324 | + fn raw_line(&self) -> u8 { |
| 325 | + *self as u8 |
| 326 | + } |
| 327 | + |
| 328 | + fn interrupt(&self) -> pac::Interrupt { |
| 329 | + use pac::Interrupt; |
| 330 | + use ConfigurableLine::*; |
| 331 | + |
| 332 | + match self { |
| 333 | + Pvd => Interrupt::PVD, |
| 334 | + RtcAlarm | RtcTamper_CssLse | RtcWakeup => Interrupt::RTC, |
| 335 | + Comp1 | Comp2 => Interrupt::ADC_COMP, |
| 336 | + } |
| 337 | + } |
| 338 | +} |
| 339 | + |
| 340 | +/// A non-configurable interrupt line. |
| 341 | +#[derive(Copy, Clone, PartialEq, Eq)] |
| 342 | +pub enum DirectLine { |
| 343 | + #[cfg(any(feature = "stm32l0x2", feature = "stm32l0x3"))] |
| 344 | + Usb = 18, |
| 345 | + I2C1 = 23, |
| 346 | + I2C3 = 24, |
| 347 | + Usart1 = 25, |
| 348 | + Usart2 = 26, |
| 349 | + // 27 = reserved |
| 350 | + Lpuart1 = 28, |
| 351 | + Lptim1 = 29, |
| 352 | +} |
| 353 | + |
| 354 | +impl ExtiLine for DirectLine { |
| 355 | + fn from_raw_line(line: u8) -> Option<Self> { |
| 356 | + use DirectLine::*; |
| 357 | + |
| 358 | + Some(match line { |
| 359 | + #[cfg(any(feature = "stm32l0x2", feature = "stm32l0x3"))] |
| 360 | + 18 => Usb, |
| 361 | + 23 => I2C1, |
| 362 | + 24 => I2C3, |
| 363 | + 25 => Usart1, |
| 364 | + 26 => Usart2, |
| 365 | + // 27 = reserved |
| 366 | + 28 => Lpuart1, |
| 367 | + 29 => Lptim1, |
| 368 | + _ => return None, |
| 369 | + }) |
| 370 | + } |
| 371 | + |
| 372 | + fn raw_line(&self) -> u8 { |
| 373 | + *self as u8 |
| 374 | + } |
| 375 | + |
| 376 | + fn interrupt(&self) -> pac::Interrupt { |
| 377 | + use pac::Interrupt; |
| 378 | + use DirectLine::*; |
| 379 | + |
| 380 | + match self { |
| 381 | + #[cfg(any(feature = "stm32l0x2", feature = "stm32l0x3"))] |
| 382 | + Usb => Interrupt::USB, |
| 383 | + I2C1 => Interrupt::I2C1, |
| 384 | + I2C3 => Interrupt::I2C3, |
| 385 | + Usart1 => Interrupt::USART1, |
| 386 | + Usart2 => Interrupt::USART2, |
| 387 | + Lpuart1 => Interrupt::AES_RNG_LPUART1, |
| 388 | + Lptim1 => Interrupt::LPTIM1, |
| 389 | + } |
| 390 | + } |
| 391 | +} |
0 commit comments