1 /*
2  * Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include "pico/stdio/driver.h"
8 #include "pico/stdio_uart.h"
9 #include "pico/binary_info.h"
10 #include "hardware/gpio.h"
11 
12 static uart_inst_t *uart_instance;
13 
14 #if PICO_STDIO_UART_SUPPORT_CHARS_AVAILABLE_CALLBACK
15 static void (*chars_available_callback)(void*);
16 static void *chars_available_param;
17 #endif
18 
19 #if PICO_NO_BI_STDIO_UART
20 #define stdio_bi_decl_if_func_used(x)
21 #else
22 #define stdio_bi_decl_if_func_used bi_decl_if_func_used
23 #endif
24 
stdio_uart_init()25 void stdio_uart_init() {
26 #ifdef uart_default
27     int tx_pin = -1;
28     int rx_pin = -1;
29 #ifdef PICO_DEFAULT_UART_TX_PIN
30     tx_pin = PICO_DEFAULT_UART_TX_PIN;
31 #ifdef PICO_DEFAULT_UART_RX_PIN
32     rx_pin = PICO_DEFAULT_UART_RX_PIN;
33     stdio_bi_decl_if_func_used(bi_program_feature("UART stdin / stdout"));
34     bi_decl_if_func_used(bi_2pins_with_func(PICO_DEFAULT_UART_RX_PIN, PICO_DEFAULT_UART_TX_PIN, GPIO_FUNC_UART));
35 #else
36     stdio_bi_decl_if_func_used(bi_program_feature("UART stdout"));
37     bi_decl_if_func_used(bi_1pin_with_func(PICO_DEFAULT_UART_TX_PIN, GPIO_FUNC_UART));
38 #endif
39 #elif defined(PICO_DEFAULT_UART_RX_PIN)
40     rx_pin = PICO_DEFAULT_UART_RX_PIN;
41     stdio_bi_decl_if_func_used(bi_program_feature("UART stdin"));
42     bi_decl_if_func_used(bi_1pin_with_func(PICO_DEFAULT_UART_RX_PIN, GPIO_FUNC_UART));
43 #endif
44 #if !defined(PICO_DEFAULT_UART_BAUD_RATE)
45     panic("UART baud rate undefined");
46 #else
47     stdio_uart_init_full(uart_default, PICO_DEFAULT_UART_BAUD_RATE, tx_pin, rx_pin);
48 #endif
49 #endif
50 }
51 
stdout_uart_init()52 void stdout_uart_init() {
53 #if defined(uart_default) && defined(PICO_DEFAULT_UART_TX_PIN)
54     bi_decl_if_func_used(bi_1pin_with_func(PICO_DEFAULT_UART_TX_PIN, GPIO_FUNC_UART));
55 #if !defined(PICO_DEFAULT_UART_BAUD_RATE)
56     panic("UART baud rate undefined");
57 #else
58     stdio_bi_decl_if_func_used(bi_program_feature("UART stdout"));
59     stdio_uart_init_full(uart_default, PICO_DEFAULT_UART_BAUD_RATE, PICO_DEFAULT_UART_TX_PIN, -1);
60 #endif
61 #endif
62 }
63 
stdin_uart_init()64 void stdin_uart_init() {
65 #if defined(uart_default) && defined(PICO_DEFAULT_UART_RX_PIN)
66     bi_decl_if_func_used(bi_1pin_with_func(PICO_DEFAULT_UART_RX_PIN, GPIO_FUNC_UART));
67 #if !defined(PICO_DEFAULT_UART_BAUD_RATE)
68     panic("UART baud rate undefined");
69 #else
70     stdio_bi_decl_if_func_used(bi_program_feature("UART stdin"));
71     stdio_uart_init_full(uart_default, PICO_DEFAULT_UART_BAUD_RATE, -1, PICO_DEFAULT_UART_RX_PIN);
72 #endif
73 #endif
74 }
75 
stdio_uart_init_full(struct uart_inst * uart,uint baud_rate,int tx_pin,int rx_pin)76 void stdio_uart_init_full(struct uart_inst *uart, uint baud_rate, int tx_pin, int rx_pin) {
77     uart_instance = uart;
78     if (tx_pin >= 0) gpio_set_function((uint)tx_pin, GPIO_FUNC_UART);
79     if (rx_pin >= 0) gpio_set_function((uint)rx_pin, GPIO_FUNC_UART);
80     uart_init(uart_instance, baud_rate);
81     stdio_set_driver_enabled(&stdio_uart, true);
82 }
83 
stdio_uart_out_chars(const char * buf,int length)84 static void stdio_uart_out_chars(const char *buf, int length) {
85     for (int i = 0; i <length; i++) {
86         uart_putc(uart_instance, buf[i]);
87     }
88 }
89 
stdio_uart_in_chars(char * buf,int length)90 int stdio_uart_in_chars(char *buf, int length) {
91     int i=0;
92     while (i<length && uart_is_readable(uart_instance)) {
93         buf[i++] = uart_getc(uart_instance);
94     }
95 #if PICO_STDIO_UART_SUPPORT_CHARS_AVAILABLE_CALLBACK
96     if (chars_available_callback) {
97         // Re-enable interrupts after reading a character
98         uart_set_irq_enables(uart_instance, true, false);
99     }
100 #endif
101     return i ? i : PICO_ERROR_NO_DATA;
102 }
103 
104 #if PICO_STDIO_UART_SUPPORT_CHARS_AVAILABLE_CALLBACK
on_uart_rx(void)105 static void on_uart_rx(void) {
106     if (chars_available_callback) {
107         // Interrupts will go off until the uart is read, so disable them
108         uart_set_irq_enables(uart_instance, false, false);
109         chars_available_callback(chars_available_param);
110     }
111 }
112 
stdio_uart_set_chars_available_callback(void (* fn)(void *),void * param)113 static void stdio_uart_set_chars_available_callback(void (*fn)(void*), void *param) {
114     static_assert(UART1_IRQ == UART0_IRQ + 1, "");
115     const uint UART_IRQ = UART0_IRQ + uart_get_index(uart_instance);
116     if (fn && !chars_available_callback) {
117         irq_set_exclusive_handler(UART_IRQ, on_uart_rx);
118         irq_set_enabled(UART_IRQ, true);
119         uart_set_irq_enables(uart_instance, true, false);
120     } else if (!fn && chars_available_callback) {
121         uart_set_irq_enables(uart_instance, false, false);
122         irq_set_enabled(UART_IRQ, false);
123         irq_remove_handler(UART_IRQ, on_uart_rx);
124     }
125     chars_available_callback = fn;
126     chars_available_param = param;
127 }
128 #endif
129 
130 stdio_driver_t stdio_uart = {
131     .out_chars = stdio_uart_out_chars,
132     .in_chars = stdio_uart_in_chars,
133 #if PICO_STDIO_UART_SUPPORT_CHARS_AVAILABLE_CALLBACK
134     .set_chars_available_callback = stdio_uart_set_chars_available_callback,
135 #endif
136 #if PICO_STDIO_ENABLE_CRLF_SUPPORT
137     .crlf_enabled = PICO_STDIO_UART_DEFAULT_CRLF
138 #endif
139 };
140