Skip to main content

msp430fr5969_hal/
lib.rs

1#![no_std]
2// Inline asm for msp430 is gated behind this nightly feature (used by
3// `delay` for its cycle-accurate busy-loop).
4#![feature(asm_experimental_arch)]
5
6pub mod adc;
7mod adc_cal;
8mod adc_seq;
9pub mod aes;
10mod baud;
11pub mod capture;
12mod capture_math;
13pub mod clocks;
14pub mod comp_e;
15mod comp_ladder;
16pub mod crc;
17mod crc_soft;
18pub mod delay;
19pub mod dma;
20pub mod fram;
21mod fram_addr;
22pub mod gpio;
23pub mod i2c;
24mod i2c_slave;
25pub mod mpu;
26mod mpu_seg;
27pub mod power;
28pub mod pwm;
29pub mod ref_a;
30pub mod rtc;
31mod rtc_alarm;
32mod rtc_tick;
33pub mod rx_queue;
34pub mod serial;
35pub mod spi;
36pub mod sys;
37mod ticks;
38pub mod timer;
39pub mod tlv;
40pub mod watchdog;
41
42/// Boot front door: optionally stop the watchdog, then take the PAC
43/// peripherals — **in that order, guaranteed by construction**.
44///
45/// The two steps are order-sensitive: the watchdog powers up running as a
46/// ~32 ms fuse, and `Peripherals::take()` enters a critical section, so the
47/// stop must come first (see [`watchdog`]). Written as two statements in every
48/// binary, nothing stops a future `main` from swapping them; fused here, the
49/// ordering cannot be gotten wrong at a call site. Make this the first
50/// statement in `main`:
51///
52/// ```ignore
53/// #[entry]
54/// fn main() -> ! {
55///     let p = hal::init(hal::watchdog::WdtMode::Hold).unwrap();
56///     // ...
57/// }
58/// ```
59///
60/// The three policies (see [`watchdog::WdtMode`]): `Hold` stops the watchdog,
61/// `Arm { source, interval }` installs a fresh timeout so boot itself runs
62/// guarded, and `LeaveRunning` performs no `WDTCTL` write at all.
63///
64/// Returns what `Peripherals::take()` returns: `Some` on the first call,
65/// `None` after (the watchdog policy is still applied either way).
66///
67/// Gated on the `critical-section` feature for the same reason the PAC gates
68/// `Peripherals::take()` on it: `take()` only exists when a critical-section
69/// implementation is available (see the `msp430` crate's
70/// `critical-section-single-core`). Without the feature there is no safe
71/// `take` to fuse with, so there is no `init` either — use
72/// [`watchdog::disable`] and `Peripherals::steal()` manually in that world.
73#[cfg(feature = "critical-section")]
74pub fn init(wdt: watchdog::WdtMode) -> Option<pac::Peripherals> {
75    match wdt {
76        watchdog::WdtMode::Hold => watchdog::disable(),
77        watchdog::WdtMode::LeaveRunning => {}
78        watchdog::WdtMode::Arm { source, interval } => watchdog::arm(source, interval),
79    }
80    pac::Peripherals::take()
81}
82
83pub use embedded_hal;
84pub use embedded_hal_nb;
85pub use embedded_io;
86pub use embedded_storage;
87pub use pac;
88
89/// Interrupt vector names for use with msp430-rt's `#[interrupt]` attribute.
90///
91/// msp430-rt's `#[interrupt]` macro validates the handler's name against a
92/// `interrupt::<NAME>` path (e.g. `interrupt::TIMER0_A1`). The PAC exposes these
93/// as variants of `pac::Interrupt` rather than as a module, so this shim
94/// re-exports them under the `interrupt` path the macro expects. Bring it into
95/// scope (`use hal::interrupt;`) alongside the `#[msp430_rt::interrupt]`
96/// attribute when defining an ISR.
97pub mod interrupt {
98    pub use crate::pac::Interrupt::*;
99}