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 
25 #ifdef PICO_DEFAULT_UART_TX_PIN
26 #if (PICO_DEFAULT_UART_TX_PIN & 0x1) || (PICO_RP2040 && (PICO_DEFAULT_UART_TX_PIN & 0x2))
27 #error "Specified PICO_DEFAULT_UART_TX_PIN does not support UART TX"
28 #endif
29 #endif
30 
31 #ifdef PICO_DEFAULT_UART_RX_PIN
32 #if !(PICO_DEFAULT_UART_RX_PIN & 0x1) || (PICO_RP2040 && (PICO_DEFAULT_UART_TX_PIN & 0x2))
33 #error "Specified PICO_DEFAULT_UART_RX_PIN does not support UART RX"
34 #endif
35 #endif
36 
stdio_uart_init(void)37 void stdio_uart_init(void) {
38 #ifdef uart_default
39     int tx_pin = -1;
40     int rx_pin = -1;
41 #ifdef PICO_DEFAULT_UART_TX_PIN
42     tx_pin = PICO_DEFAULT_UART_TX_PIN;
43 #ifdef PICO_DEFAULT_UART_RX_PIN
44     rx_pin = PICO_DEFAULT_UART_RX_PIN;
45     stdio_bi_decl_if_func_used(bi_program_feature("UART stdin / stdout"));
46 #if PICO_DEFAULT_UART_TX_PIN == PICO_DEFAULT_UART_RX_PIN
47     bi_decl_if_func_used(bi_2pins_with_func(PICO_DEFAULT_UART_RX_PIN, PICO_DEFAULT_UART_TX_PIN, uart_get_funcsel(uart_default, PICO_DEFAULT_UART_RX_PIN)));
48 #else
49     bi_decl_if_func_used(bi_1pin_with_func(PICO_DEFAULT_UART_TX_PIN, UART_FUNCSEL_NUM(uart_default, PICO_DEFAULT_UART_TX_PIN)));
50     bi_decl_if_func_used(bi_1pin_with_func(PICO_DEFAULT_UART_RX_PIN, UART_FUNCSEL_NUM(uart_default, PICO_DEFAULT_UART_RX_PIN)));
51 #endif
52 #else
53     stdio_bi_decl_if_func_used(bi_program_feature("UART stdout"));
54     bi_decl_if_func_used(bi_1pin_with_func(PICO_DEFAULT_UART_TX_PIN, GPIO_FUNC_UART));
55 #endif
56 #elif defined(PICO_DEFAULT_UART_RX_PIN)
57     rx_pin = PICO_DEFAULT_UART_RX_PIN;
58     stdio_bi_decl_if_func_used(bi_program_feature("UART stdin"));
59     bi_decl_if_func_used(bi_1pin_with_func(PICO_DEFAULT_UART_RX_PIN, GPIO_FUNC_UART));
60 #endif
61 #if !defined(PICO_DEFAULT_UART_BAUD_RATE)
62     panic("UART baud rate undefined");
63 #else
64     stdio_uart_init_full(uart_default, PICO_DEFAULT_UART_BAUD_RATE, tx_pin, rx_pin);
65 #endif
66 #endif
67 }
68 
stdout_uart_init(void)69 void stdout_uart_init(void) {
70 #if defined(uart_default) && defined(PICO_DEFAULT_UART_TX_PIN)
71     bi_decl_if_func_used(bi_1pin_with_func(PICO_DEFAULT_UART_TX_PIN, UART_FUNCSEL_NUM(uart_default, PICO_DEFAULT_UART_TX_PIN)));
72 #if !defined(PICO_DEFAULT_UART_BAUD_RATE)
73     panic("UART baud rate undefined");
74 #else
75     stdio_bi_decl_if_func_used(bi_program_feature("UART stdout"));
76     stdio_uart_init_full(uart_default, PICO_DEFAULT_UART_BAUD_RATE, PICO_DEFAULT_UART_TX_PIN, -1);
77 #endif
78 #endif
79 }
80 
stdin_uart_init(void)81 void stdin_uart_init(void) {
82 #if defined(uart_default) && defined(PICO_DEFAULT_UART_RX_PIN)
83     bi_decl_if_func_used(bi_1pin_with_func(PICO_DEFAULT_UART_RX_PIN, UART_FUNCSEL_NUM(uart_default, PICO_DEFAULT_UART_RX_PIN)));
84 #if !defined(PICO_DEFAULT_UART_BAUD_RATE)
85     panic("UART baud rate undefined");
86 #else
87     stdio_bi_decl_if_func_used(bi_program_feature("UART stdin"));
88     stdio_uart_init_full(uart_default, PICO_DEFAULT_UART_BAUD_RATE, -1, PICO_DEFAULT_UART_RX_PIN);
89 #endif
90 #endif
91 }
92 
stdio_uart_init_full(struct uart_inst * uart,uint baud_rate,int tx_pin,int rx_pin)93 void stdio_uart_init_full(struct uart_inst *uart, uint baud_rate, int tx_pin, int rx_pin) {
94     uart_instance = uart;
95     if (tx_pin >= 0) gpio_set_function((uint)tx_pin, UART_FUNCSEL_NUM(uart, tx_pin));
96     if (rx_pin >= 0) gpio_set_function((uint)rx_pin, UART_FUNCSEL_NUM(uart, rx_pin));
97     uart_init(uart_instance, baud_rate);
98     stdio_set_driver_enabled(&stdio_uart, true);
99 }
100 
stdio_uart_deinit(void)101 void stdio_uart_deinit(void) {
102 #ifdef uart_default
103     int tx_pin = -1;
104     int rx_pin = -1;
105 #ifdef PICO_DEFAULT_UART_TX_PIN
106     tx_pin = PICO_DEFAULT_UART_TX_PIN;
107 #endif
108 #ifdef PICO_DEFAULT_UART_RX_PIN
109     rx_pin = PICO_DEFAULT_UART_RX_PIN;
110 #endif
111     stdio_uart_deinit_full(uart_default, tx_pin, rx_pin);
112 #endif
113 }
114 
stdout_uart_deinit(void)115 void stdout_uart_deinit(void) {
116 #if defined(uart_default) && defined(PICO_DEFAULT_UART_TX_PIN)
117     stdio_uart_deinit_full(uart_default, PICO_DEFAULT_UART_TX_PIN, -1);
118 #endif
119 }
120 
stdin_uart_deinit(void)121 void stdin_uart_deinit(void) {
122 #if defined(uart_default) && defined(PICO_DEFAULT_UART_RX_PIN)
123     stdio_uart_deinit_full(uart_default, -1, PICO_DEFAULT_UART_RX_PIN);
124 #endif
125 }
126 
stdio_uart_deinit_full(struct uart_inst * uart,int tx_pin,int rx_pin)127 void stdio_uart_deinit_full(struct uart_inst *uart, int tx_pin, int rx_pin) {
128     uart_instance = uart;
129     stdio_set_driver_enabled(&stdio_uart, false);
130     uart_deinit(uart_instance);
131 #if PICO_RP2040
132     ((void)tx_pin);
133     ((void)rx_pin);
134 #else
135     // Leave pads isolated
136     if (tx_pin >= 0) hw_set_bits(&pads_bank0_hw->io[tx_pin], PADS_BANK0_GPIO0_ISO_BITS);
137     if (rx_pin >= 0) hw_set_bits(&pads_bank0_hw->io[rx_pin], PADS_BANK0_GPIO0_ISO_BITS);
138 #endif
139 }
140 
stdio_uart_out_chars(const char * buf,int length)141 static void stdio_uart_out_chars(const char *buf, int length) {
142     for (int i = 0; i <length; i++) {
143         uart_putc(uart_instance, buf[i]);
144     }
145 }
146 
stdio_uart_in_chars(char * buf,int length)147 int stdio_uart_in_chars(char *buf, int length) {
148     int i=0;
149     while (i<length && uart_is_readable(uart_instance)) {
150         buf[i++] = uart_getc(uart_instance);
151     }
152 #if PICO_STDIO_UART_SUPPORT_CHARS_AVAILABLE_CALLBACK
153     if (chars_available_callback) {
154         // Re-enable interrupts after reading a character
155         uart_set_irqs_enabled(uart_instance, true, false);
156     }
157 #endif
158     return i ? i : PICO_ERROR_NO_DATA;
159 }
160 
161 #if PICO_STDIO_UART_SUPPORT_CHARS_AVAILABLE_CALLBACK
on_uart_rx(void)162 static void on_uart_rx(void) {
163     if (chars_available_callback) {
164         // Interrupts will go off until the uart is read, so disable them
165         uart_set_irqs_enabled(uart_instance, false, false);
166         chars_available_callback(chars_available_param);
167     }
168 }
169 
170 #include "hardware/irq.h"
171 
stdio_uart_set_chars_available_callback(void (* fn)(void *),void * param)172 static void stdio_uart_set_chars_available_callback(void (*fn)(void*), void *param) {
173     uint irq_num = UART_IRQ_NUM(uart_instance);
174     if (fn && !chars_available_callback) {
175         irq_set_exclusive_handler(irq_num, on_uart_rx);
176         irq_set_enabled(irq_num, true);
177         uart_set_irqs_enabled(uart_instance, true, false);
178     } else if (!fn && chars_available_callback) {
179         uart_set_irqs_enabled(uart_instance, false, false);
180         irq_set_enabled(irq_num, false);
181         irq_remove_handler(irq_num, on_uart_rx);
182     }
183     chars_available_callback = fn;
184     chars_available_param = param;
185 }
186 #endif
187 
stdio_uart_out_flush(void)188 static void stdio_uart_out_flush(void) {
189     uart_default_tx_wait_blocking();
190 }
191 
192 stdio_driver_t stdio_uart = {
193     .out_chars = stdio_uart_out_chars,
194     .out_flush = stdio_uart_out_flush,
195     .in_chars = stdio_uart_in_chars,
196 #if PICO_STDIO_UART_SUPPORT_CHARS_AVAILABLE_CALLBACK
197     .set_chars_available_callback = stdio_uart_set_chars_available_callback,
198 #endif
199 #if PICO_STDIO_ENABLE_CRLF_SUPPORT
200     .crlf_enabled = PICO_STDIO_UART_DEFAULT_CRLF
201 #endif
202 };
203