imxrt_uart_panic/
lib.rs

1#![no_std]
2#![deny(unsafe_code)]
3#![deny(missing_docs)]
4#![doc = include_str!("../README.md")]
5#![doc(issue_tracker_base_url = "https://github.com/imxrt-rs/imxrt-uart-panic/issues")]
6#![cfg_attr(docsrs, feature(doc_cfg))]
7
8#[doc(hidden)]
9pub mod _deps {
10    pub use cortex_m;
11    pub use embedded_io;
12    pub use imxrt_hal;
13    pub use imxrt_ral;
14}
15
16/// Registers the UART panic handler.
17///
18/// # Arguments
19///
20/// - `uart`: A peripheral defined in [`imxrt_ral::lpuart`].
21/// - `tx_pin`: The UART tx pin. Usually defined in the bsp, such as [`teensy4_bsp::pins::common`](https://docs.rs/teensy4-pins/0.3.2/teensy4_pins/common).
22/// - `rx_pin`: The UART rx pin. Usually defined in the bsp, such as [`teensy4_bsp::pins::common`](https://docs.rs/teensy4-pins/0.3.2/teensy4_pins/common).
23/// - `baud`: The UART baud rate. Most common ones are `9600` and `115200`.
24/// - `idle_func`: Optional. Specifies what function to enter in the end. Default is [`cortex_m::asm::udf`], but this could
25///   for example be used to enter [`teensy4_panic::sos`](https://docs.rs/teensy4-panic/0.2.3/teensy4_panic/fn.sos.html).
26#[macro_export]
27macro_rules! register {
28    ($uart: ident, $tx_pin: ident, $rx_pin: ident, $baud: expr, $idle_func: expr) => {
29        #[panic_handler]
30        fn panic(info: &::core::panic::PanicInfo) -> ! {
31            use ::core::fmt::Write as _;
32
33            use $crate::_deps::embedded_io::Write as _;
34            use $crate::_deps::imxrt_hal as hal;
35            use $crate::_deps::imxrt_ral as ral;
36
37            use hal::ccm;
38            use hal::lpuart::{Baud, Direction, Lpuart, Pins, Watermark};
39
40            // Initialize clocks
41            const UART_DIVIDER: u32 = 3;
42            pub const UART_FREQUENCY: u32 = hal::ccm::XTAL_OSCILLATOR_HZ / UART_DIVIDER;
43            let mut ccm = unsafe { ral::ccm::CCM::instance() };
44            ccm::clock_gate::UART_CLOCK_GATES
45                .iter()
46                .for_each(|locator| locator.set(&mut ccm, ccm::clock_gate::OFF));
47            ccm::uart_clk::set_selection(&mut ccm, ccm::uart_clk::Selection::Oscillator);
48            ccm::uart_clk::set_divider(&mut ccm, UART_DIVIDER);
49            ccm::clock_gate::UART_CLOCK_GATES
50                .iter()
51                .for_each(|locator| locator.set(&mut ccm, ccm::clock_gate::ON));
52
53            // Initialize UART
54            let registers = unsafe { ral::lpuart::$uart::instance() };
55            let pins = Pins {
56                tx: unsafe { $tx_pin::new() },
57                rx: unsafe { $rx_pin::new() },
58            };
59            let mut uart = Lpuart::new(registers, pins);
60
61            // Configure UART
62            const BAUD: Baud = Baud::compute(UART_FREQUENCY, $baud);
63            uart.disable(|uart| {
64                uart.set_baud(&BAUD);
65                uart.enable_fifo(Watermark::tx(4));
66                uart.disable_fifo(Direction::Rx);
67            });
68
69            struct UartWriter<P, const N: u8> {
70                uart: hal::lpuart::Lpuart<P, N>,
71            }
72            impl<P, const N: u8> ::core::fmt::Write for UartWriter<P, N> {
73                fn write_str(&mut self, s: &str) -> ::core::fmt::Result {
74                    for &b in s.as_bytes() {
75                        if b == b'\n' {
76                            let _ = self.uart.write_all(b"\r");
77                        }
78                        let _ = self.uart.write_all(core::slice::from_ref(&b));
79                    }
80                    Ok(())
81                }
82            }
83
84            let mut uart = UartWriter { uart };
85
86            ::core::writeln!(uart).ok();
87            ::core::writeln!(uart, "{}", info).ok();
88            ::core::writeln!(uart).ok();
89
90            let _ = uart.uart.flush();
91
92            $idle_func();
93        }
94    };
95    ($uart: ident, $tx_pin: ident, $rx_pin: ident, $baud: expr) => {
96        $crate::register!(
97            $uart,
98            $tx_pin,
99            $rx_pin,
100            $baud,
101            $crate::_deps::cortex_m::asm::udf
102        );
103    };
104}