1 /*
2 * Copyright (c) 2006-2023, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2009-02-05 Bernard first version
9 * 2009-10-25 Bernard fix rt_serial_read bug when there is no data
10 * in the buffer.
11 * 2010-03-29 Bernard cleanup code.
12 * 2010-03-30 Kyle Ported from STM32 to AVR32.
13 * 2023-10-25 Raman Gopalan UART driver for at32uc3a: Initial version
14 * 2023-11-06 Raman Gopalan Driver abstractions for uc3a and uc3b devices
15 */
16
17 #include <rthw.h>
18 #include <rtthread.h>
19 #include <rtdevice.h>
20 #include "drv_uart.h"
21
22 #ifdef RT_USING_SERIAL
23
24 #include "compiler.h"
25 #include "usart.h"
26 #include "gpio.h"
27 #include "intc.h"
28
29 #if !defined(BSP_USING_UART0) && !defined(BSP_USING_UART1)
30 #error "Please define at least one BSP_USING_UARTx"
31 /* this driver can be disabled at menuconfig -> RT-Thread Components -> Device Drivers */
32 #endif
33
34 #ifdef BSP_USING_UART0
35 void avr32uc3_uart0_isr(void);
36 #endif
37
38 #ifdef BSP_USING_UART1
39 void avr32uc3_uart1_isr(void);
40 #endif
41
42 #ifdef BSP_USING_UART2
43 void avr32uc3_uart2_isr(void);
44 #endif
45
46 /* AVR32UC3B uart driver */
47 struct avr32uc3_uart_dev
48 {
49 rt_serial_t parent;
50 avr32_usart_t *instance;
51 rt_uint32_t irqno;
52 rt_uint32_t irq_level;
53 rt_uint32_t tx_pin;
54 rt_uint32_t tx_pin_function;
55 rt_uint32_t rx_pin;
56 rt_uint32_t rx_pin_function;
57 void (*uart_isr)(void);
58 };
59
60 static struct avr32uc3_uart_dev uart_dev[] =
61 {
62 #ifdef BSP_USING_UART0
63 {
64 .instance = (avr32_usart_t *)&AVR32_USART0,
65 .irqno = AVR32_USART0_IRQ,
66 .irq_level = AVR32_INTC_INT0,
67 .tx_pin = BSP_UART0_TX_PIN,
68 .tx_pin_function = BSP_UART0_TX_PIN_FUNCTION,
69 .rx_pin = BSP_UART0_RX_PIN,
70 .rx_pin_function = BSP_UART0_RX_PIN_FUNCTION,
71 .uart_isr = avr32uc3_uart0_isr,
72 },
73 #endif
74
75 #ifdef BSP_USING_UART1
76 {
77 .instance = (avr32_usart_t *)&AVR32_USART1,
78 .irqno = AVR32_USART1_IRQ,
79 .irq_level = AVR32_INTC_INT0,
80 .tx_pin = BSP_UART1_TX_PIN,
81 .tx_pin_function = BSP_UART1_TX_PIN_FUNCTION,
82 .rx_pin = BSP_UART1_RX_PIN,
83 .rx_pin_function = BSP_UART1_RX_PIN_FUNCTION,
84 .uart_isr = avr32uc3_uart1_isr,
85 },
86 #endif
87
88 #ifdef BSP_USING_UART2
89 {
90 .instance = (avr32_usart_t *)&AVR32_USART2,
91 .irqno = AVR32_USART2_IRQ,
92 .irq_level = AVR32_INTC_INT0,
93 .tx_pin = BSP_UART2_TX_PIN,
94 .tx_pin_function = BSP_UART2_TX_PIN_FUNCTION,
95 .rx_pin = BSP_UART2_RX_PIN,
96 .rx_pin_function = BSP_UART2_RX_PIN_FUNCTION,
97 .uart_isr = avr32uc3_uart2_isr,
98 },
99 #endif
100 };
101
102 enum
103 {
104 #ifdef BSP_USING_UART0
105 UART0_INDEX,
106 #endif
107
108 #ifdef BSP_USING_UART1
109 UART1_INDEX,
110 #endif
111
112 #ifdef BSP_USING_UART2
113 UART2_INDEX,
114 #endif
115 };
116
117 #ifdef BSP_USING_UART0
avr32uc3_uart0_isr(void)118 void avr32uc3_uart0_isr(void)
119 {
120 rt_interrupt_enter();
121 /* read interrupt status and clear it */
122 if (usart_test_hit(&AVR32_USART0)) /* rx ind */
123 {
124 rt_hw_serial_isr(&uart_dev[UART0_INDEX].parent, RT_SERIAL_EVENT_RX_IND);
125 }
126
127 rt_interrupt_leave();
128 }
129 #endif
130
131 #ifdef BSP_USING_UART1
avr32uc3_uart1_isr(void)132 void avr32uc3_uart1_isr(void)
133 {
134 rt_interrupt_enter();
135 /* read interrupt status and clear it */
136 if (usart_test_hit(&AVR32_USART1)) /* rx ind */
137 {
138 rt_hw_serial_isr(&uart_dev[UART1_INDEX].parent, RT_SERIAL_EVENT_RX_IND);
139 }
140
141 rt_interrupt_leave();
142 }
143 #endif
144
145 #ifdef BSP_USING_UART2
avr32uc3_uart2_isr(void)146 void avr32uc3_uart2_isr(void)
147 {
148 rt_interrupt_enter();
149 /* read interrupt status and clear it */
150 if (usart_test_hit(&AVR32_USART2)) /* rx ind */
151 {
152 rt_hw_serial_isr(&uart_dev[UART2_INDEX].parent, RT_SERIAL_EVENT_RX_IND);
153 }
154
155 rt_interrupt_leave();
156 }
157 #endif
158
159 /**
160 * @addtogroup AVR32UC3
161 */
162 /*@{*/
163
avr32uc3_uart_configure(struct rt_serial_device * serial,struct serial_configure * cfg)164 static rt_err_t avr32uc3_uart_configure(struct rt_serial_device *serial, struct serial_configure *cfg)
165 {
166 struct avr32uc3_uart_dev *uart = RT_NULL;
167 unsigned char l_parity;
168 unsigned short l_stop;
169 unsigned long l_baud;
170 unsigned char l_data_bits;
171
172 RT_ASSERT(serial != RT_NULL);
173 RT_ASSERT(cfg != RT_NULL);
174
175 uart = rt_container_of(serial, struct avr32uc3_uart_dev, parent);
176 // Set the TX and RX pins by using the function select on the GPIO
177 // Set datasheet for more information on function select
178 gpio_enable_module_pin(uart->tx_pin, uart->tx_pin_function);
179 gpio_enable_module_pin(uart->rx_pin, uart->rx_pin_function);
180
181 /* Parity settings */
182 if (cfg->parity == PARITY_ODD)
183 l_parity = USART_ODD_PARITY;
184 else if (cfg->parity == PARITY_EVEN)
185 l_parity = USART_EVEN_PARITY;
186 else
187 l_parity = USART_NO_PARITY;
188
189 /* Stopbit settings */
190 if (cfg->stop_bits == STOP_BITS_1)
191 l_stop = USART_1_STOPBIT;
192 else
193 l_stop = USART_2_STOPBITS;
194
195 l_baud = cfg->baud_rate;
196 l_data_bits = cfg->data_bits;
197
198 /* Populate */
199 usart_options_t usart_options = {
200 .baudrate = l_baud,
201 .charlength = l_data_bits,
202 .paritytype = l_parity,
203 .stopbits = l_stop,
204 .channelmode = USART_NORMAL_CHMODE
205 };
206
207 usart_init_rs232(uart->instance, &usart_options, FPBA);
208
209 return RT_EOK;
210 }
211
avr32uc3_uart_control(struct rt_serial_device * serial,int cmd,void * arg)212 static rt_err_t avr32uc3_uart_control(struct rt_serial_device *serial, int cmd, void *arg)
213 {
214 struct avr32uc3_uart_dev *uart = RT_NULL;
215 RT_ASSERT(serial != RT_NULL);
216 uart = rt_container_of(serial, struct avr32uc3_uart_dev, parent);
217
218 switch (cmd)
219 {
220 /* enable interrupt */
221 case RT_DEVICE_CTRL_SET_INT:
222 // Set up a RX interrupt
223 // We need to set up the handler first
224 // And set up and enable the interrupt handlers
225 //INTC_init_interrupts();
226 INTC_register_interrupt(uart->uart_isr, uart->irqno, uart->irq_level);
227 uart->instance->ier = AVR32_USART_IER_RXRDY_MASK;
228 break;
229 }
230 return RT_EOK;
231 }
232
avr32uc3_uart_putc(struct rt_serial_device * serial,char c)233 static int avr32uc3_uart_putc(struct rt_serial_device *serial, char c)
234 {
235 struct avr32uc3_uart_dev *uart = RT_NULL;
236 RT_ASSERT(serial != RT_NULL);
237 uart = rt_container_of(serial, struct avr32uc3_uart_dev, parent);
238 usart_putchar(uart->instance, c);
239
240 return 1;
241 }
242
avr32uc3_uart_getc(struct rt_serial_device * serial)243 static int avr32uc3_uart_getc(struct rt_serial_device *serial)
244 {
245 struct avr32uc3_uart_dev *uart = RT_NULL;
246 RT_ASSERT(serial != RT_NULL);
247 uart = rt_container_of(serial, struct avr32uc3_uart_dev, parent);
248
249 int ch;
250 if (usart_read_char(uart->instance, &ch) == USART_SUCCESS)
251 return ch;
252
253 return -1;
254 }
255
256 const static struct rt_uart_ops _uart_ops =
257 {
258 avr32uc3_uart_configure,
259 avr32uc3_uart_control,
260 avr32uc3_uart_putc,
261 avr32uc3_uart_getc,
262 RT_NULL,
263 };
264
265 /*
266 * UART Initiation
267 */
rt_hw_uart_init(void)268 int rt_hw_uart_init(void)
269 {
270 rt_err_t ret = RT_EOK;
271
272 struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;
273
274 #ifdef BSP_USING_UART0
275 uart_dev[UART0_INDEX].parent.ops = &_uart_ops;
276 uart_dev[UART0_INDEX].parent.config = config;
277
278 ret = rt_hw_serial_register(&uart_dev[UART0_INDEX].parent,
279 "uart0",
280 RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX,
281 &uart_dev[UART0_INDEX]);
282 RT_ASSERT(ret == RT_EOK);
283 #endif
284
285 #ifdef BSP_USING_UART1
286 uart_dev[UART1_INDEX].parent.ops = &_uart_ops;
287 uart_dev[UART1_INDEX].parent.config = config;
288
289 ret = rt_hw_serial_register(&uart_dev[UART1_INDEX].parent,
290 "uart1",
291 RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX,
292 &uart_dev[UART1_INDEX]);
293 RT_ASSERT(ret == RT_EOK);
294 #endif
295
296 #ifdef BSP_USING_UART2
297 uart_dev[UART2_INDEX].parent.ops = &_uart_ops;
298 uart_dev[UART2_INDEX].parent.config = config;
299
300 ret = rt_hw_serial_register(&uart_dev[UART2_INDEX].parent,
301 "uart2",
302 RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX,
303 &uart_dev[UART2_INDEX]);
304 RT_ASSERT(ret == RT_EOK);
305 #endif
306
307
308 return ret;
309 }
310
311 #endif /* RT_USING_SERIAL */
312
313 /*@}*/
314