nano_rp2040_connect/
io.rs

1// Licensed under the Apache License, Version 2.0 or the MIT License.
2// SPDX-License-Identifier: Apache-2.0 OR MIT
3// Copyright Tock Contributors 2022.
4
5use core::fmt::Write;
6use core::panic::PanicInfo;
7
8use kernel::debug::{self, IoWrite};
9use kernel::hil::led::LedHigh;
10use kernel::hil::uart::{Configure, Parameters, Parity, StopBits, Width};
11use kernel::utilities::cells::OptionalCell;
12
13use rp2040::gpio::{GpioFunction, RPGpio, RPGpioPin};
14use rp2040::uart::Uart;
15
16/// Writer is used by kernel::debug to panic message to the serial port.
17pub struct Writer {
18    uart: OptionalCell<&'static Uart<'static>>,
19}
20
21impl Writer {
22    pub fn set_uart(&self, uart: &'static Uart) {
23        self.uart.set(uart);
24    }
25
26    fn write_to_uart(&self, uart: &Uart, buf: &[u8]) {
27        for &c in buf {
28            uart.send_byte(c);
29        }
30    }
31}
32
33/// Global static for debug writer
34pub static mut WRITER: Writer = Writer {
35    uart: OptionalCell::empty(),
36};
37
38impl Write for Writer {
39    fn write_str(&mut self, s: &str) -> ::core::fmt::Result {
40        self.write(s.as_bytes());
41        Ok(())
42    }
43}
44
45impl IoWrite for Writer {
46    fn write(&mut self, buf: &[u8]) -> usize {
47        self.uart.map_or_else(
48            || {
49                // If no UART is configured for panic print, use UART0
50                let uart0 = &Uart::new_uart0();
51
52                if !uart0.is_configured() {
53                    let parameters = Parameters {
54                        baud_rate: 115200,
55                        width: Width::Eight,
56                        parity: Parity::None,
57                        stop_bits: StopBits::One,
58                        hw_flow_control: false,
59                    };
60                    //configure parameters of uart for sending bytes
61                    let _result = uart0.configure(parameters);
62                    //set RX and TX pins in UART mode
63                    let gpio_tx = RPGpioPin::new(RPGpio::GPIO0);
64                    let gpio_rx = RPGpioPin::new(RPGpio::GPIO1);
65                    gpio_rx.set_function(GpioFunction::UART);
66                    gpio_tx.set_function(GpioFunction::UART);
67                }
68
69                self.write_to_uart(uart0, buf);
70            },
71            |uart| {
72                self.write_to_uart(uart, buf);
73            },
74        );
75        buf.len()
76    }
77}
78
79/// Default panic handler for the Arduino Nano RP2040 Connect board.
80///
81/// We just use the standard default provided by the debug module in the kernel.
82#[cfg(not(test))]
83#[panic_handler]
84pub unsafe fn panic_fmt(pi: &PanicInfo) -> ! {
85    // LED is connected to GPIO 25
86
87    use core::ptr::addr_of_mut;
88    let led_kernel_pin = &RPGpioPin::new(RPGpio::GPIO25);
89    let led = &mut LedHigh::new(led_kernel_pin);
90    let writer = &mut *addr_of_mut!(WRITER);
91
92    debug::panic(
93        &mut [led],
94        writer,
95        pi,
96        &cortexm0p::support::nop,
97        crate::PANIC_RESOURCES.get(),
98    )
99}