1 /*
2 * Copyright (c) 2006-2021, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2020-06-27 AHTYDHD the first version
9 */
10
11 #include "drv_uart.h"
12 #include <stdint.h>
13 #include <stdbool.h>
14 #include "inc/hw_memmap.h"
15 #include "inc/hw_ints.h"
16 #include "driverlib/sysctl.h"
17 #include "driverlib/gpio.h"
18 #include "driverlib/pin_map.h"
19 #include "driverlib/interrupt.h"
20 #include "driverlib/uart.h"
21
22 #ifdef RT_USING_SERIAL
23 #include "uart_config.h"
24 #include "tm4c123_config.h"
25
26 #define LOG_TAG "drv.uart"
27 #include <drv_log.h>
28
29 #if !defined(BSP_USING_UART0)&&!defined(BSP_USING_UART1)&&!defined(BSP_USING_UART2)&&!defined(BSP_USING_UART3)
30 #error "Please define at least one BSP_USING_UARTx"
31 #endif
32
33 enum
34 {
35 #ifdef BSP_USING_UART0
36 UART0_INDEX,
37 #endif
38 #ifdef BSP_USING_UART1
39 UART1_INDEX,
40 #endif
41 #ifdef BSP_USING_UART2
42 UART2_INDEX,
43 #endif
44 #ifdef BSP_USING_UART3
45 UART3_INDEX,
46 #endif
47 };
48
49 uint32_t uart_intbase[] =
50 {
51 #ifdef BSP_USING_UART0
52 INT_UART0,
53 #endif
54 #ifdef BSP_USING_UART1
55 INT_UART1,
56 #endif
57 #ifdef BSP_USING_UART2
58 INT_UART2,
59 #endif
60 #ifdef BSP_USING_UART3
61 INT_UART3
62 #endif
63 };
64
65 static struct tm4c123_uart_config uart_config[] =
66 {
67 #ifdef BSP_USING_UART0
68 UART0_CONFIG,
69 #endif
70
71 #ifdef BSP_USING_UART1
72 UART1_CONFIG,
73 #endif
74
75 #ifdef BSP_USING_UART2
76 UART2_CONFIG,
77 #endif
78
79 #ifdef BSP_USING_UART3
80 UART3_CONFIG,
81 #endif
82 };
83 static struct tm4c123_uart uart_obj[sizeof(uart_config) / sizeof(uart_config[0])] = {0};
84
tm4c123_configure(struct rt_serial_device * serial,struct serial_configure * cfg)85 static rt_err_t tm4c123_configure(struct rt_serial_device *serial, struct serial_configure *cfg)
86 {
87 struct tm4c123_uart *uart;
88 RT_ASSERT(serial != RT_NULL);
89 RT_ASSERT(cfg != RT_NULL);
90 uart = rt_container_of(serial, struct tm4c123_uart, serial);
91
92 UARTFIFOLevelSet(uart->config->uartbase, UART_FIFO_TX1_8, UART_FIFO_RX1_8);
93 UARTConfigSetExpClk(uart->config->uartbase, SysCtlClockGet(), uart->config->baudrate,
94 uart->config->mode);
95 return RT_EOK;
96 }
97
98
tm4c123_control(struct rt_serial_device * serial,int cmd,void * arg)99 static rt_err_t tm4c123_control(struct rt_serial_device *serial, int cmd, void *arg)
100 {
101 struct tm4c123_uart *uart;
102 RT_ASSERT(serial != RT_NULL);
103 uart = rt_container_of(serial, struct tm4c123_uart, serial);
104
105 switch (cmd)
106 {
107 /* disable interrupt */
108 case RT_DEVICE_CTRL_CLR_INT:
109 /* disable rx irq */
110 IntDisable(uart->uartintbase);
111 UARTIntDisable(uart->config->uartbase, UART_INT_RX);
112 break;
113 /* enable interrupt */
114 case RT_DEVICE_CTRL_SET_INT:
115 /* enable rx irq */
116 IntEnable(uart->uartintbase);
117 UARTIntEnable(uart->config->uartbase, UART_INT_RX);
118 break;
119 }
120 return RT_EOK;
121 }
122
tm4c123_putc(struct rt_serial_device * serial,char c)123 static int tm4c123_putc(struct rt_serial_device *serial, char c)
124 {
125 struct tm4c123_uart *uart;
126 RT_ASSERT(serial != RT_NULL);
127
128 uart = rt_container_of(serial, struct tm4c123_uart, serial);
129 UARTCharPut(uart->config->uartbase, c);
130 return 1;
131 }
132
tm4c123_getc(struct rt_serial_device * serial)133 static int tm4c123_getc(struct rt_serial_device *serial)
134 {
135 int ch;
136 struct tm4c123_uart *uart;
137 RT_ASSERT(serial != RT_NULL);
138
139 uart = rt_container_of(serial, struct tm4c123_uart, serial);
140 ch = -1;
141 ch = UARTCharGetNonBlocking(uart->config->uartbase);
142 return ch;
143 }
144
tm4c123_dma_transmit(struct rt_serial_device * serial,rt_uint8_t * buf,rt_size_t size,int direction)145 static rt_ssize_t tm4c123_dma_transmit(struct rt_serial_device *serial, rt_uint8_t *buf, rt_size_t size, int direction)
146 {
147 /* this is an interface for uart dma, reserved for uptate. */
148 return 0;
149 }
150
151 static const struct rt_uart_ops tm4c123_uart_ops =
152 {
153 .configure = tm4c123_configure,
154 .control = tm4c123_control,
155 .putc = tm4c123_putc,
156 .getc = tm4c123_getc,
157 .dma_transmit = tm4c123_dma_transmit
158 };
159
160 /**
161 * Uart common interrupt process. This need add to uart ISR.
162 *
163 * @param serial serial device
164 */
uart_isr(struct rt_serial_device * serial)165 static void uart_isr(struct rt_serial_device *serial)
166 {
167 struct tm4c123_uart *uart;
168 uint32_t ui32Ints;
169 RT_ASSERT(serial != RT_NULL);
170 uart = rt_container_of(serial, struct tm4c123_uart, serial);
171
172 ui32Ints = UARTIntStatus(uart->config->uartbase, true);
173 UARTIntClear(uart->config->uartbase, ui32Ints);
174
175 /* UART in mode Receiver -------------------------------------------------*/
176 if (ui32Ints & (UART_INT_RX | UART_INT_RT))
177 {
178 rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_IND);
179 }
180 }
181
182 #if defined(BSP_USING_UART0)
UART0IntHandler(void)183 void UART0IntHandler(void)
184 {
185 /* enter interrupt */
186 rt_interrupt_enter();
187
188 uart_isr(&(uart_obj[UART0_INDEX].serial));
189 /* leave interrupt */
190 rt_interrupt_leave();
191 }
192 #endif /* BSP_USING_UART0 */
193
194 #if defined(BSP_USING_UART1)
UART1IntHandler(void)195 void UART1IntHandler(void)
196 {
197 /* enter interrupt */
198 rt_interrupt_enter();
199
200 uart_isr(&(uart_obj[UART1_INDEX].serial));
201 /* leave interrupt */
202 rt_interrupt_leave();
203 }
204 #endif /* BSP_USING_UART1 */
205
tm4c123_uart_get_dma_config(void)206 static void tm4c123_uart_get_dma_config(void)
207 {
208 /* this is an interface for uart dma, reserved for update */
209 }
210
rt_hw_usart_init(void)211 int rt_hw_usart_init(void)
212 {
213 rt_size_t obj_num = sizeof(uart_obj) / sizeof(struct tm4c123_uart);
214 struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;
215 rt_err_t result = 0;
216
217 uart_hw_config();
218 for (int i = 0; i < obj_num; i++)
219 {
220 uart_obj[i].config = &uart_config[i];
221 uart_obj[i].uartintbase = uart_intbase[i];
222 uart_obj[i].serial.ops = &tm4c123_uart_ops;
223 uart_obj[i].serial.config = config;
224 /* register UART device */
225 result = rt_hw_serial_register(&uart_obj[i].serial, uart_obj[i].config->name,
226 RT_DEVICE_FLAG_RDWR
227 | RT_DEVICE_FLAG_INT_RX
228 | RT_DEVICE_FLAG_INT_TX
229 | uart_obj[i].uart_dma_flag
230 , NULL);
231 RT_ASSERT(result == RT_EOK);
232 }
233 return result;
234 }
235
236 #endif /* RT_USING_SERIAL */
237
238 /************************** end of file ******************/
239