raspberry_pi_pico/
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 configure_uart(&self, uart: &Uart) {
27        if !uart.is_configured() {
28            let parameters = Parameters {
29                baud_rate: 115200,
30                width: Width::Eight,
31                parity: Parity::None,
32                stop_bits: StopBits::One,
33                hw_flow_control: false,
34            };
35            //configure parameters of uart for sending bytes
36            let _ = uart.configure(parameters);
37            //set RX and TX pins in UART mode
38            let gpio_tx = RPGpioPin::new(RPGpio::GPIO0);
39            let gpio_rx = RPGpioPin::new(RPGpio::GPIO1);
40            gpio_rx.set_function(GpioFunction::UART);
41            gpio_tx.set_function(GpioFunction::UART);
42        }
43    }
44
45    fn write_to_uart(&self, uart: &Uart, buf: &[u8]) {
46        for &c in buf {
47            uart.send_byte(c);
48        }
49    }
50}
51
52/// Global static for debug writer
53pub static mut WRITER: Writer = Writer {
54    uart: OptionalCell::empty(),
55};
56
57impl Write for Writer {
58    fn write_str(&mut self, s: &str) -> ::core::fmt::Result {
59        self.write(s.as_bytes());
60        Ok(())
61    }
62}
63
64impl IoWrite for Writer {
65    fn write(&mut self, buf: &[u8]) -> usize {
66        self.uart.map_or_else(
67            || {
68                let uart = Uart::new_uart0();
69                self.configure_uart(&uart);
70                self.write_to_uart(&uart, buf);
71            },
72            |uart| {
73                self.configure_uart(uart);
74                self.write_to_uart(uart, buf);
75            },
76        );
77        buf.len()
78    }
79}
80
81/// Default panic handler for the Raspberry Pi Pico board.
82///
83/// We just use the standard default provided by the debug module in the kernel.
84#[cfg(not(test))]
85#[panic_handler]
86pub unsafe fn panic_fmt(pi: &PanicInfo) -> ! {
87    // LED is connected to GPIO 25
88
89    use core::ptr::addr_of_mut;
90    let led_kernel_pin = &RPGpioPin::new(RPGpio::GPIO25);
91    let led = &mut LedHigh::new(led_kernel_pin);
92    let writer = &mut *addr_of_mut!(WRITER);
93
94    debug::panic(
95        &mut [led],
96        writer,
97        pi,
98        &cortexm0p::support::nop,
99        crate::PANIC_RESOURCES.get(),
100    )
101}