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