|
5 | 5 | * |
6 | 6 | * Change Logs: |
7 | 7 | * Date Author Notes |
| 8 | + * 2023-09-26 1ridic Integrate with RT-Thread driver framework. |
8 | 9 | */ |
9 | 10 |
|
10 | 11 | #include <rthw.h> |
|
13 | 14 | #include "board.h" |
14 | 15 | #include "drv_uart.h" |
15 | 16 |
|
| 17 | +#ifdef RT_USING_SERIAL |
| 18 | + |
16 | 19 | #include "hardware/uart.h" |
17 | 20 | #include "hardware/irq.h" |
18 | 21 |
|
19 | | -#define UART_ID uart0 |
20 | | -#define BAUD_RATE 115200 |
21 | | -#define DATA_BITS 8 |
22 | | -#define STOP_BITS 1 |
23 | | -#define PARITY UART_PARITY_NONE |
24 | | - |
25 | | -// We are using pins 0 and 1, but see the GPIO function select table in the |
26 | | -// datasheet for information on which other pins can be used. |
27 | | -#define UART_TX_PIN 0 |
28 | | -#define UART_RX_PIN 1 |
| 22 | +#if !defined(BSP_USING_UART0) && !defined(BSP_USING_UART1) |
| 23 | + #error "Please define at least one BSP_USING_UARTx" |
| 24 | + /* this driver can be disabled at menuconfig -> RT-Thread Components -> Device Drivers */ |
| 25 | +#endif |
29 | 26 |
|
30 | | -#define PICO_UART_DEVICE(uart) (struct pico_uart_dev *)(uart) |
31 | | - |
32 | | -static struct pico_uart_dev uart0_dev; |
| 27 | +#ifdef BSP_USING_UART0 |
| 28 | + void pico_uart0_isr(void); |
| 29 | +#endif |
| 30 | +#ifdef BSP_USING_UART1 |
| 31 | + void pico_uart1_isr(void); |
| 32 | +#endif |
33 | 33 |
|
34 | 34 | struct pico_uart_dev |
35 | 35 | { |
36 | | - struct rt_serial_device parent; |
37 | | - rt_uint32_t uart_periph; |
| 36 | + rt_serial_t parent; |
| 37 | + uart_inst_t *instance; |
38 | 38 | rt_uint32_t irqno; |
| 39 | + rt_uint32_t tx_pin; |
| 40 | + rt_uint32_t rx_pin; |
| 41 | + void (*uart_isr)(void); |
39 | 42 | }; |
40 | 43 |
|
41 | | -void pico_uart_isr(void) |
| 44 | +static struct pico_uart_dev uart_dev[] = |
42 | 45 | { |
43 | | - rt_interrupt_enter(); |
44 | | - /* read interrupt status and clear it */ |
45 | | - if (uart_is_readable(uart0)) /* rx ind */ |
| 46 | +#ifdef BSP_USING_UART0 |
46 | 47 | { |
47 | | - rt_hw_serial_isr(&uart0_dev.parent, RT_SERIAL_EVENT_RX_IND); |
48 | | - } |
49 | | - |
50 | | - rt_interrupt_leave(); |
51 | | -} |
| 48 | + .instance = uart0, |
| 49 | + .irqno = UART0_IRQ, |
| 50 | + .tx_pin = BSP_UART0_TX_PIN, |
| 51 | + .rx_pin = BSP_UART0_RX_PIN, |
| 52 | + .uart_isr = pico_uart0_isr, |
| 53 | + }, |
| 54 | +#endif |
| 55 | +#ifdef BSP_USING_UART1 |
| 56 | + { |
| 57 | + .instance = uart1, |
| 58 | + .irqno = UART1_IRQ, |
| 59 | + .tx_pin = BSP_UART1_TX_PIN, |
| 60 | + .rx_pin = BSP_UART1_RX_PIN, |
| 61 | + .uart_isr = pico_uart1_isr, |
| 62 | + }, |
| 63 | +#endif |
| 64 | +}; |
52 | 65 |
|
53 | | -/* |
54 | | - * UART interface |
55 | | - */ |
56 | | -static rt_err_t pico_uart_configure(struct rt_serial_device *serial, struct serial_configure *cfg) |
| 66 | +enum |
57 | 67 | { |
58 | | - return RT_EOK; |
59 | | -} |
| 68 | +#ifdef BSP_USING_UART0 |
| 69 | + UART0_INDEX, |
| 70 | +#endif |
| 71 | +#ifdef BSP_USING_UART1 |
| 72 | + UART1_INDEX, |
| 73 | +#endif |
| 74 | +}; |
60 | 75 |
|
61 | | -static rt_err_t pico_uart_control(struct rt_serial_device *serial, int cmd, void *arg) |
| 76 | +#ifdef BSP_USING_UART0 |
| 77 | +void pico_uart0_isr(void) |
62 | 78 | { |
63 | | - // Select correct interrupt for the UART we are using |
64 | | - int UART_IRQ = UART_ID == uart0 ? UART0_IRQ : UART1_IRQ; |
65 | | - |
66 | | - switch (cmd) |
| 79 | + rt_interrupt_enter(); |
| 80 | + /* read interrupt status and clear it */ |
| 81 | + if (uart_is_readable(uart0)) /* rx ind */ |
67 | 82 | { |
68 | | - /* enable interrupt */ |
69 | | - case RT_DEVICE_CTRL_SET_INT: |
70 | | - // Set up a RX interrupt |
71 | | - // We need to set up the handler first |
72 | | - // And set up and enable the interrupt handlers |
73 | | - irq_set_exclusive_handler(UART_IRQ, pico_uart_isr); |
74 | | - irq_set_enabled(UART_IRQ, true); |
75 | | - |
76 | | - // Now enable the UART to send interrupts - RX only |
77 | | - uart_set_irq_enables(UART_ID, true, false); |
78 | | - break; |
| 83 | + rt_hw_serial_isr(&uart_dev[UART0_INDEX].parent, RT_SERIAL_EVENT_RX_IND); |
79 | 84 | } |
80 | | - return RT_EOK; |
81 | | -} |
82 | 85 |
|
83 | | -static int pico_uart_putc(struct rt_serial_device *serial, char c) |
84 | | -{ |
85 | | - uart_putc_raw(uart0, c); |
86 | | - |
87 | | - return 1; |
| 86 | + rt_interrupt_leave(); |
88 | 87 | } |
89 | | - |
90 | | -static int pico_uart_getc(struct rt_serial_device *serial) |
| 88 | +#endif |
| 89 | +#ifdef BSP_USING_UART1 |
| 90 | +void pico_uart1_isr(void) |
91 | 91 | { |
92 | | - int ch; |
93 | | - |
94 | | - if (uart_is_readable(uart0)) |
95 | | - { |
96 | | - ch = uart_get_hw(uart0)->dr; |
97 | | - } |
98 | | - else |
| 92 | + rt_interrupt_enter(); |
| 93 | + /* read interrupt status and clear it */ |
| 94 | + if (uart_is_readable(uart1)) /* rx ind */ |
99 | 95 | { |
100 | | - ch =-1; |
| 96 | + rt_hw_serial_isr(&uart_dev[UART1_INDEX].parent, RT_SERIAL_EVENT_RX_IND); |
101 | 97 | } |
102 | 98 |
|
103 | | - return ch; |
| 99 | + rt_interrupt_leave(); |
104 | 100 | } |
105 | | - |
106 | | -const static struct rt_uart_ops _uart_ops = |
107 | | -{ |
108 | | - pico_uart_configure, |
109 | | - pico_uart_control, |
110 | | - pico_uart_putc, |
111 | | - pico_uart_getc, |
112 | | - RT_NULL, |
113 | | -}; |
| 101 | +#endif |
114 | 102 |
|
115 | 103 | /* |
116 | | - * UART Initiation |
| 104 | + * UART interface |
117 | 105 | */ |
118 | | -int rt_hw_uart_init(void) |
| 106 | +static rt_err_t pico_uart_configure(struct rt_serial_device *serial, struct serial_configure *cfg) |
119 | 107 | { |
120 | | - rt_err_t ret = RT_EOK; |
121 | | - |
122 | | - struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT; |
| 108 | + struct pico_uart_dev *uart = RT_NULL; |
| 109 | + RT_ASSERT(serial != RT_NULL); |
| 110 | + RT_ASSERT(cfg != RT_NULL); |
| 111 | + uart = rt_container_of(serial, struct pico_uart_dev, parent); |
123 | 112 |
|
124 | | - uart_init(UART_ID, 115200); |
| 113 | + uart_init(uart->instance, cfg->baud_rate); |
125 | 114 |
|
126 | 115 | // Set the TX and RX pins by using the function select on the GPIO |
127 | 116 | // Set datasheet for more information on function select |
128 | | - gpio_set_function(UART_TX_PIN, GPIO_FUNC_UART); |
129 | | - gpio_set_function(UART_RX_PIN, GPIO_FUNC_UART); |
130 | | - |
131 | | - // Actually, we want a different speed |
132 | | - // The call will return the actual baud rate selected, which will be as close as |
133 | | - // possible to that requested |
134 | | - uart_set_baudrate(UART_ID, BAUD_RATE); |
| 117 | + gpio_set_function(uart->rx_pin, GPIO_FUNC_UART); |
| 118 | + gpio_set_function(uart->tx_pin, GPIO_FUNC_UART); |
135 | 119 |
|
136 | 120 | // Set UART flow control CTS/RTS, we don't want these, so turn them off |
137 | | - uart_set_hw_flow(UART_ID, false, false); |
| 121 | + uart_set_hw_flow(uart->instance, false, false); |
138 | 122 |
|
139 | 123 | // Set our data format |
140 | | - uart_set_format(UART_ID, DATA_BITS, STOP_BITS, PARITY); |
| 124 | + uart_set_format(uart->instance, cfg->data_bits, cfg->stop_bits, UART_PARITY_NONE); |
141 | 125 |
|
142 | 126 | // Turn off FIFO's - we want to do this character by character |
143 | | - uart_set_fifo_enabled(UART_ID, false); |
144 | | - |
145 | | - uart0_dev.parent.ops = &_uart_ops; |
146 | | - uart0_dev.parent.config = config; |
147 | | - |
148 | | - ret = rt_hw_serial_register(&uart0_dev.parent, |
149 | | - "uart0", |
150 | | - RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX, |
151 | | - &uart0_dev); |
152 | | - |
153 | | - return ret; |
154 | | -} |
155 | | -// INIT_DEVICE_EXPORT(rt_hw_uart_init); |
| 127 | + uart_set_fifo_enabled(uart->instance, false); |
156 | 128 |
|
157 | | -// We are using pins 0 and 1, but see the GPIO function select table in the |
158 | | -// datasheet for information on which other pins can be used. |
159 | | -#define UART1_TX_PIN 4 |
160 | | -#define UART1_RX_PIN 5 |
161 | | - |
162 | | -static struct pico_uart1_dev uart1_dev; |
163 | | - |
164 | | -struct pico_uart1_dev |
165 | | -{ |
166 | | - struct rt_serial_device parent; |
167 | | - rt_uint32_t uart_periph; |
168 | | - rt_uint32_t irqno; |
169 | | -}; |
170 | | - |
171 | | -void pico_uart1_isr(void) |
172 | | -{ |
173 | | - rt_interrupt_enter(); |
174 | | - /* read interrupt status and clear it */ |
175 | | - if (uart_is_readable(uart1)) /* rx ind */ |
176 | | - { |
177 | | - rt_hw_serial_isr(&uart1_dev.parent, RT_SERIAL_EVENT_RX_IND); |
178 | | - } |
179 | | - |
180 | | - rt_interrupt_leave(); |
181 | | -} |
182 | | - |
183 | | -/* |
184 | | - * UART interface |
185 | | - */ |
186 | | -static rt_err_t pico_uart1_configure(struct rt_serial_device *serial, struct serial_configure *cfg) |
187 | | -{ |
188 | 129 | return RT_EOK; |
189 | 130 | } |
190 | 131 |
|
191 | | -static rt_err_t pico_uart1_control(struct rt_serial_device *serial, int cmd, void *arg) |
| 132 | +static rt_err_t pico_uart_control(struct rt_serial_device *serial, int cmd, void *arg) |
192 | 133 | { |
| 134 | + struct pico_uart_dev *uart = RT_NULL; |
| 135 | + RT_ASSERT(serial != RT_NULL); |
| 136 | + uart = rt_container_of(serial, struct pico_uart_dev, parent); |
| 137 | + |
193 | 138 | switch (cmd) |
194 | 139 | { |
195 | 140 | /* enable interrupt */ |
196 | 141 | case RT_DEVICE_CTRL_SET_INT: |
197 | 142 | // Set up a RX interrupt |
198 | 143 | // We need to set up the handler first |
199 | 144 | // And set up and enable the interrupt handlers |
200 | | - irq_set_exclusive_handler(UART1_IRQ, pico_uart1_isr); |
201 | | - irq_set_enabled(UART1_IRQ, true); |
| 145 | + irq_set_exclusive_handler(uart->irqno, uart->uart_isr); |
| 146 | + irq_set_enabled(uart->irqno, true); |
202 | 147 |
|
203 | 148 | // Now enable the UART to send interrupts - RX only |
204 | | - uart_set_irq_enables(uart1, true, false); |
| 149 | + uart_set_irq_enables(uart->instance, true, false); |
205 | 150 | break; |
206 | 151 | } |
207 | 152 | return RT_EOK; |
208 | 153 | } |
209 | 154 |
|
210 | | -static int pico_uart1_putc(struct rt_serial_device *serial, char c) |
| 155 | +static int pico_uart_putc(struct rt_serial_device *serial, char c) |
211 | 156 | { |
212 | | - uart_putc_raw(uart1, c); |
| 157 | + struct pico_uart_dev *uart = RT_NULL; |
| 158 | + RT_ASSERT(serial != RT_NULL); |
| 159 | + uart = rt_container_of(serial, struct pico_uart_dev, parent); |
| 160 | + uart_putc_raw(uart->instance, c); |
213 | 161 |
|
214 | 162 | return 1; |
215 | 163 | } |
216 | 164 |
|
217 | | -static int pico_uart1_getc(struct rt_serial_device *serial) |
| 165 | +static int pico_uart_getc(struct rt_serial_device *serial) |
218 | 166 | { |
| 167 | + struct pico_uart_dev *uart = RT_NULL; |
| 168 | + RT_ASSERT(serial != RT_NULL); |
| 169 | + uart = rt_container_of(serial, struct pico_uart_dev, parent); |
| 170 | + |
219 | 171 | int ch; |
220 | 172 |
|
221 | | - if (uart_is_readable(uart1)) |
| 173 | + if (uart_is_readable(uart->instance)) |
222 | 174 | { |
223 | | - ch = uart_get_hw(uart1)->dr; |
| 175 | + ch = uart_get_hw(uart->instance)->dr; |
224 | 176 | } |
225 | 177 | else |
226 | 178 | { |
227 | | - ch =-1; |
| 179 | + ch = -1; |
228 | 180 | } |
229 | 181 |
|
230 | 182 | return ch; |
231 | 183 | } |
232 | 184 |
|
233 | | -const static struct rt_uart_ops _uart1_ops = |
| 185 | +const static struct rt_uart_ops _uart_ops = |
234 | 186 | { |
235 | | - pico_uart1_configure, |
236 | | - pico_uart1_control, |
237 | | - pico_uart1_putc, |
238 | | - pico_uart1_getc, |
| 187 | + pico_uart_configure, |
| 188 | + pico_uart_control, |
| 189 | + pico_uart_putc, |
| 190 | + pico_uart_getc, |
239 | 191 | RT_NULL, |
240 | 192 | }; |
241 | 193 |
|
242 | 194 | /* |
243 | 195 | * UART Initiation |
244 | 196 | */ |
245 | | -int rt_hw_uart1_init(void) |
| 197 | +int rt_hw_uart_init(void) |
246 | 198 | { |
247 | 199 | rt_err_t ret = RT_EOK; |
248 | 200 |
|
249 | 201 | struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT; |
250 | 202 |
|
251 | | - uart_init(uart1, 115200); |
252 | | - |
253 | | - // Set the TX and RX pins by using the function select on the GPIO |
254 | | - // Set datasheet for more information on function select |
255 | | - gpio_set_function(UART1_TX_PIN, GPIO_FUNC_UART); |
256 | | - gpio_set_function(UART1_RX_PIN, GPIO_FUNC_UART); |
257 | | - |
258 | | - // Actually, we want a different speed |
259 | | - // The call will return the actual baud rate selected, which will be as close as |
260 | | - // possible to that requested |
261 | | - uart_set_baudrate(uart1, BAUD_RATE); |
262 | | - |
263 | | - // Set UART flow control CTS/RTS, we don't want these, so turn them off |
264 | | - uart_set_hw_flow(uart1, false, false); |
| 203 | +#ifdef BSP_USING_UART0 |
| 204 | + uart_dev[UART0_INDEX].parent.ops = &_uart_ops; |
| 205 | + uart_dev[UART0_INDEX].parent.config = config; |
265 | 206 |
|
266 | | - // Set our data format |
267 | | - uart_set_format(uart1, DATA_BITS, STOP_BITS, PARITY); |
268 | | - |
269 | | - // Turn off FIFO's - we want to do this character by character |
270 | | - uart_set_fifo_enabled(uart1, false); |
| 207 | + ret = rt_hw_serial_register(&uart_dev[UART0_INDEX].parent, |
| 208 | + "uart0", |
| 209 | + RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX, |
| 210 | + &uart_dev[UART0_INDEX]); |
| 211 | + RT_ASSERT(ret == RT_EOK); |
| 212 | +#endif |
271 | 213 |
|
272 | | - uart1_dev.parent.ops = &_uart1_ops; |
273 | | - uart1_dev.parent.config = config; |
| 214 | +#ifdef BSP_USING_UART1 |
| 215 | + uart_dev[UART1_INDEX].parent.ops = &_uart_ops; |
| 216 | + uart_dev[UART1_INDEX].parent.config = config; |
274 | 217 |
|
275 | | - ret = rt_hw_serial_register(&uart1_dev.parent, |
| 218 | + ret = rt_hw_serial_register(&uart_dev[UART1_INDEX].parent, |
276 | 219 | "uart1", |
277 | 220 | RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX, |
278 | | - &uart1_dev); |
| 221 | + &uart_dev[UART1_INDEX]); |
| 222 | + RT_ASSERT(ret == RT_EOK); |
| 223 | +#endif |
279 | 224 |
|
280 | 225 | return ret; |
281 | 226 | } |
282 | | -INIT_DEVICE_EXPORT(rt_hw_uart1_init); |
| 227 | + |
| 228 | + |
| 229 | +#endif /* RT_USING_SERIAL */ |
0 commit comments