1 /*
2 * Copyright (c) 2006-2018, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2023-09-26 1ridic Integrate with RT-Thread driver framework.
9 */
10
11 #include <rtdevice.h>
12 #include <drv_uart.h>
13 #include <hardware/gpio.h>
14
15 #ifdef RT_USING_SERIAL
16
17 #include "hardware/uart.h"
18 #include "hardware/irq.h"
19
20 #if !defined(BSP_USING_UART0) && !defined(BSP_USING_UART1)
21 #error "Please define at least one BSP_USING_UARTx"
22 /* this driver can be disabled at menuconfig -> RT-Thread Components -> Device Drivers */
23 #endif
24
25 #ifdef BSP_USING_UART0
26 void pico_uart0_isr(void);
27 #endif
28 #ifdef BSP_USING_UART1
29 void pico_uart1_isr(void);
30 #endif
31
32 struct pico_uart_dev
33 {
34 rt_serial_t parent;
35 uart_inst_t *instance;
36 rt_uint32_t irqno;
37 rt_uint32_t tx_pin;
38 rt_uint32_t rx_pin;
39 void (*uart_isr)(void);
40 };
41
42 static struct pico_uart_dev uart_dev[] =
43 {
44 #ifdef BSP_USING_UART0
45 {
46 .instance = uart0,
47 .irqno = UART0_IRQ,
48 .tx_pin = BSP_UART0_TX_PIN,
49 .rx_pin = BSP_UART0_RX_PIN,
50 .uart_isr = pico_uart0_isr,
51 },
52 #endif
53 #ifdef BSP_USING_UART1
54 {
55 .instance = uart1,
56 .irqno = UART1_IRQ,
57 .tx_pin = BSP_UART1_TX_PIN,
58 .rx_pin = BSP_UART1_RX_PIN,
59 .uart_isr = pico_uart1_isr,
60 },
61 #endif
62 };
63
64 enum
65 {
66 #ifdef BSP_USING_UART0
67 UART0_INDEX,
68 #endif
69 #ifdef BSP_USING_UART1
70 UART1_INDEX,
71 #endif
72 };
73
74 #ifdef BSP_USING_UART0
pico_uart0_isr(void)75 void pico_uart0_isr(void)
76 {
77 rt_interrupt_enter();
78 /* read interrupt status and clear it */
79 if (uart_is_readable(uart0)) /* rx ind */
80 {
81 rt_hw_serial_isr(&uart_dev[UART0_INDEX].parent, RT_SERIAL_EVENT_RX_IND);
82 }
83
84 rt_interrupt_leave();
85 }
86 #endif
87 #ifdef BSP_USING_UART1
pico_uart1_isr(void)88 void pico_uart1_isr(void)
89 {
90 rt_interrupt_enter();
91 /* read interrupt status and clear it */
92 if (uart_is_readable(uart1)) /* rx ind */
93 {
94 rt_hw_serial_isr(&uart_dev[UART1_INDEX].parent, RT_SERIAL_EVENT_RX_IND);
95 }
96
97 rt_interrupt_leave();
98 }
99 #endif
100
101 /*
102 * UART interface
103 */
pico_uart_configure(struct rt_serial_device * serial,struct serial_configure * cfg)104 static rt_err_t pico_uart_configure(struct rt_serial_device *serial, struct serial_configure *cfg)
105 {
106 struct pico_uart_dev *uart = RT_NULL;
107 RT_ASSERT(serial != RT_NULL);
108 RT_ASSERT(cfg != RT_NULL);
109 uart = rt_container_of(serial, struct pico_uart_dev, parent);
110
111 uart_init(uart->instance, cfg->baud_rate);
112
113 // Set the TX and RX pins by using the function select on the GPIO
114 // Set datasheet for more information on function select
115 gpio_set_function(uart->rx_pin, GPIO_FUNC_UART);
116 gpio_set_function(uart->tx_pin, GPIO_FUNC_UART);
117
118 // Set UART flow control CTS/RTS
119 if (cfg->flowcontrol == RT_SERIAL_FLOWCONTROL_CTSRTS)
120 uart_set_hw_flow(uart->instance, true, true);
121 else
122 uart_set_hw_flow(uart->instance, false, false);
123
124 // Set our data format
125 uart_parity_t uart_parity = UART_PARITY_NONE;
126 if (cfg->parity == PARITY_ODD)
127 uart_parity = UART_PARITY_ODD;
128 else if (cfg->parity == PARITY_EVEN)
129 uart_parity = UART_PARITY_EVEN;
130 uart_set_format(uart->instance, cfg->data_bits, cfg->stop_bits, uart_parity);
131
132 // Turn off FIFO's - we want to do this character by character
133 uart_set_fifo_enabled(uart->instance, false);
134
135 return RT_EOK;
136 }
137
pico_uart_control(struct rt_serial_device * serial,int cmd,void * arg)138 static rt_err_t pico_uart_control(struct rt_serial_device *serial, int cmd, void *arg)
139 {
140 struct pico_uart_dev *uart = RT_NULL;
141 RT_ASSERT(serial != RT_NULL);
142 uart = rt_container_of(serial, struct pico_uart_dev, parent);
143
144 switch (cmd)
145 {
146 /* enable interrupt */
147 case RT_DEVICE_CTRL_SET_INT:
148 // Set up a RX interrupt
149 // We need to set up the handler first
150 // And set up and enable the interrupt handlers
151 irq_set_exclusive_handler(uart->irqno, uart->uart_isr);
152 irq_set_enabled(uart->irqno, true);
153
154 // Now enable the UART to send interrupts - RX only
155 uart_set_irq_enables(uart->instance, true, false);
156 break;
157 }
158 return RT_EOK;
159 }
160
pico_uart_putc(struct rt_serial_device * serial,char c)161 static int pico_uart_putc(struct rt_serial_device *serial, char c)
162 {
163 struct pico_uart_dev *uart = RT_NULL;
164 RT_ASSERT(serial != RT_NULL);
165 uart = rt_container_of(serial, struct pico_uart_dev, parent);
166 uart_putc_raw(uart->instance, c);
167
168 return 1;
169 }
170
pico_uart_getc(struct rt_serial_device * serial)171 static int pico_uart_getc(struct rt_serial_device *serial)
172 {
173 struct pico_uart_dev *uart = RT_NULL;
174 RT_ASSERT(serial != RT_NULL);
175 uart = rt_container_of(serial, struct pico_uart_dev, parent);
176
177 int ch;
178
179 if (uart_is_readable(uart->instance))
180 {
181 ch = uart_get_hw(uart->instance)->dr;
182 }
183 else
184 {
185 ch = -1;
186 }
187
188 return ch;
189 }
190
191 const static struct rt_uart_ops _uart_ops =
192 {
193 pico_uart_configure,
194 pico_uart_control,
195 pico_uart_putc,
196 pico_uart_getc,
197 RT_NULL,
198 };
199
200 /*
201 * UART Initiation
202 */
rt_hw_uart_init(void)203 int rt_hw_uart_init(void)
204 {
205 rt_err_t ret = RT_EOK;
206
207 struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;
208
209 #ifdef BSP_USING_UART0
210 uart_dev[UART0_INDEX].parent.ops = &_uart_ops;
211 uart_dev[UART0_INDEX].parent.config = config;
212
213 ret = rt_hw_serial_register(&uart_dev[UART0_INDEX].parent,
214 "uart0",
215 RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX,
216 &uart_dev[UART0_INDEX]);
217 RT_ASSERT(ret == RT_EOK);
218 #endif
219
220 #ifdef BSP_USING_UART1
221 uart_dev[UART1_INDEX].parent.ops = &_uart_ops;
222 uart_dev[UART1_INDEX].parent.config = config;
223
224 ret = rt_hw_serial_register(&uart_dev[UART1_INDEX].parent,
225 "uart1",
226 RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX,
227 &uart_dev[UART1_INDEX]);
228 RT_ASSERT(ret == RT_EOK);
229 #endif
230
231 return ret;
232 }
233
234
235 #endif /* RT_USING_SERIAL */
236