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