1 /*
2 * File : serial.c
3 * This file is part of RT-Thread RTOS
4 * COPYRIGHT (C) 2006, RT-Thread Development Team
5 *
6 * The license and distribution terms for this file may be
7 * found in the file LICENSE in this distribution or at
8 * http://openlab.rt-thread.com/license/LICENSE
9 *
10 * Change Logs:
11 * Date Author Notes
12 * 2009-06-11 Bernard first version
13 */
14
15 #include <rthw.h>
16 #include <rtthread.h>
17
18 #include <inc/hw_types.h>
19 #include <inc/hw_memmap.h>
20 #include <inc/hw_uart.h>
21 #include <inc/hw_ints.h>
22 #include <driverlib/gpio.h>
23 #include <driverlib/sysctl.h>
24 #include <driverlib/interrupt.h>
25
26 #include <driverlib/uart.h>
27 #include "board.h"
28
29 extern void rt_hw_interrupt_thread_switch(void);
30
31 #define RT_UART_RX_BUFFER_SIZE 64
32
33 /* LM3S serial device */
34 struct rt_lm3s_serial
35 {
36 /* inherit from device */
37 struct rt_device parent;
38
39 rt_uint32_t hw_base;
40 rt_uint32_t baudrate;
41
42 /* reception field */
43 rt_uint16_t save_index, read_index;
44 rt_uint8_t rx_buffer[RT_UART_RX_BUFFER_SIZE];
45 };
46
47 #ifdef RT_USING_UART1
48 struct rt_lm3s_serial serial1;
49 #endif
50 #ifdef RT_USING_UART2
51 struct rt_lm3s_serial serial2;
52 #endif
53
54 void rt_hw_serial_init(void);
55
rt_hw_uart_isr(struct rt_lm3s_serial * serial)56 void rt_hw_uart_isr(struct rt_lm3s_serial* serial)
57 {
58 rt_device_t device;
59 rt_uint32_t status;
60
61 device = (struct rt_device*)serial;
62 status = UARTIntStatus(serial->hw_base, true);
63
64 /* clear interrupt status */
65 UARTIntClear(serial->hw_base, status);
66
67 if (device->flag & RT_DEVICE_FLAG_INT_RX)
68 {
69 char ch;
70 rt_base_t level;
71
72 while (UARTCharsAvail(serial->hw_base))
73 {
74 ch = UARTCharGetNonBlocking(serial->hw_base);
75
76 /* disable interrupt */
77 level = rt_hw_interrupt_disable();
78
79 /* read character */
80 serial->rx_buffer[serial->save_index] = ch;
81 serial->save_index ++;
82 if (serial->save_index >= RT_UART_RX_BUFFER_SIZE)
83 serial->save_index = 0;
84
85 /* if the next position is read index, discard this 'read char' */
86 if (serial->save_index == serial->read_index)
87 {
88 serial->read_index ++;
89 if (serial->read_index >= RT_UART_RX_BUFFER_SIZE)
90 serial->read_index = 0;
91 }
92
93 /* enable interrupt */
94 rt_hw_interrupt_enable(level);
95 }
96
97 /* invoke callback */
98 if(device->rx_indicate != RT_NULL)
99 {
100 rt_int32_t length;
101
102 length = serial->save_index - serial->read_index;
103 if (length < 0) length += RT_UART_RX_BUFFER_SIZE;
104 device->rx_indicate(device, length);
105 }
106 }
107 }
108
109 #ifdef RT_USING_UART1
rt_hw_uart_isr_1(int irqno)110 void rt_hw_uart_isr_1(int irqno)
111 {
112 /* enter interrupt */
113 rt_interrupt_enter();
114
115 /* get serial device */
116 rt_hw_uart_isr(&serial1);
117
118 /* leave interrupt */
119 rt_interrupt_leave();
120 rt_hw_interrupt_thread_switch();
121 }
122 #endif
123
124 #ifdef RT_USING_UART2
rt_hw_uart_isr_2(int irqno)125 void rt_hw_uart_isr_2(int irqno)
126 {
127 /* enter interrupt */
128 rt_interrupt_enter();
129
130 /* get serial device */
131 rt_hw_uart_isr(&serial2);
132
133 /* leave interrupt */
134 rt_interrupt_leave();
135 rt_hw_interrupt_thread_switch();
136 }
137 #endif
138
139 /**
140 * @addtogroup LM3S
141 */
142 /*@{*/
143
rt_serial_init(rt_device_t dev)144 static rt_err_t rt_serial_init (rt_device_t dev)
145 {
146 return RT_EOK;
147 }
148
rt_serial_open(rt_device_t dev,rt_uint16_t oflag)149 static rt_err_t rt_serial_open(rt_device_t dev, rt_uint16_t oflag)
150 {
151 struct rt_lm3s_serial* serial;
152 serial = (struct rt_lm3s_serial*) dev;
153
154 RT_ASSERT(serial != RT_NULL);
155
156 if (dev->flag & RT_DEVICE_FLAG_INT_RX)
157 {
158 /* enable interrupt */
159 if (serial->hw_base == UART0_BASE)
160 IntEnable(INT_UART0);
161 else if (serial->hw_base == UART1_BASE)
162 IntEnable(INT_UART1);
163
164 UARTIntEnable(serial->hw_base, UART_INT_RX | UART_INT_RT);
165 }
166
167 return RT_EOK;
168 }
169
rt_serial_close(rt_device_t dev)170 static rt_err_t rt_serial_close(rt_device_t dev)
171 {
172 struct rt_lm3s_serial* serial;
173 serial = (struct rt_lm3s_serial*) dev;
174
175 RT_ASSERT(serial != RT_NULL);
176
177 if (dev->flag & RT_DEVICE_FLAG_INT_RX)
178 {
179 /* disable UART rx interrupt */
180 UARTIntDisable(serial->hw_base, UART_INT_RX | UART_INT_RT);
181 }
182
183 return RT_EOK;
184 }
185
rt_serial_control(rt_device_t dev,int cmd,void * args)186 static rt_err_t rt_serial_control(rt_device_t dev, int cmd, void *args)
187 {
188 return RT_EOK;
189 }
190
rt_serial_read(rt_device_t dev,rt_off_t pos,void * buffer,rt_size_t size)191 static rt_ssize_t rt_serial_read(rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size)
192 {
193 rt_uint8_t* ptr;
194 struct rt_lm3s_serial *serial = (struct rt_lm3s_serial*)dev;
195 RT_ASSERT(serial != RT_NULL);
196
197 /* point to buffer */
198 ptr = (rt_uint8_t*) buffer;
199
200 if (dev->flag & RT_DEVICE_FLAG_INT_RX)
201 {
202 while (size)
203 {
204 /* interrupt receive */
205 rt_base_t level;
206
207 /* disable interrupt */
208 level = rt_hw_interrupt_disable();
209 if (serial->read_index != serial->save_index)
210 {
211 *ptr = serial->rx_buffer[serial->read_index];
212
213 serial->read_index ++;
214 if (serial->read_index >= RT_UART_RX_BUFFER_SIZE)
215 serial->read_index = 0;
216 }
217 else
218 {
219 /* no data in rx buffer */
220
221 /* enable interrupt */
222 rt_hw_interrupt_enable(level);
223 break;
224 }
225
226 /* enable interrupt */
227 rt_hw_interrupt_enable(level);
228
229 ptr ++; size --;
230 }
231
232 return (rt_uint32_t)ptr - (rt_uint32_t)buffer;
233 }
234 else if (dev->flag & RT_DEVICE_FLAG_DMA_RX)
235 {
236 /* not support right now */
237 RT_ASSERT(0);
238 }
239
240 /* polling mode */
241 while (size)
242 {
243 *ptr = UARTCharGetNonBlocking(serial->hw_base);
244
245 ptr ++; size --;
246 }
247
248 return (rt_size_t)ptr - (rt_size_t)buffer;
249 }
250
rt_serial_write(rt_device_t dev,rt_off_t pos,const void * buffer,rt_size_t size)251 static rt_ssize_t rt_serial_write(rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size)
252 {
253 struct rt_lm3s_serial* serial;
254 char *ptr;
255
256 serial = (struct rt_lm3s_serial*) dev;
257 if (dev->flag & RT_DEVICE_FLAG_INT_TX)
258 {
259 /* not support */
260 RT_ASSERT(0);
261 }
262 else if (dev->flag & RT_DEVICE_FLAG_DMA_TX)
263 {
264 /* not support */
265 RT_ASSERT(0);
266 }
267
268 /* polling write */
269 ptr = (char *)buffer;
270
271 if (dev->flag & RT_DEVICE_FLAG_STREAM)
272 {
273 /* stream mode */
274 while (size)
275 {
276 if (*ptr == '\n')
277 while (UARTCharPutNonBlocking(serial->hw_base, '\r') == false);
278
279 while (UARTCharPutNonBlocking(serial->hw_base, *ptr) == false);
280
281 ptr ++;
282 size --;
283 }
284 }
285 else
286 {
287 while (size)
288 {
289 while (UARTCharPutNonBlocking(serial->hw_base, *ptr) == false);
290
291 ptr ++;
292 size --;
293 }
294 }
295
296 return (rt_size_t) ptr - (rt_size_t) buffer;
297 }
298
rt_hw_serial_init(void)299 void rt_hw_serial_init(void)
300 {
301 struct rt_lm3s_serial* serial;
302
303 #ifdef RT_USING_UART1
304 serial = &serial1;
305
306 serial->parent.type = RT_Device_Class_Char;
307
308 serial->hw_base = UART0_BASE;
309 serial->baudrate = 115200;
310
311 rt_memset(serial->rx_buffer, 0, sizeof(serial->rx_buffer));
312 serial->read_index = serial->save_index = 0;
313
314 /* enable UART0 clock */
315 SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
316 SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
317
318 /* set UART0 pinmux */
319 GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
320
321 /* Configure the UART for 115,200, 8-N-1 operation. */
322 UARTConfigSetExpClk(UART0_BASE, SysCtlClockGet(), serial->baudrate,
323 (UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE |
324 UART_CONFIG_PAR_NONE));
325
326 serial->parent.init = rt_serial_init;
327 serial->parent.open = rt_serial_open;
328 serial->parent.close = rt_serial_close;
329 serial->parent.read = rt_serial_read;
330 serial->parent.write = rt_serial_write;
331 serial->parent.control = rt_serial_control;
332 serial->parent.user_data = RT_NULL;
333
334 rt_device_register(&serial->parent,
335 "uart1", RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX);
336 #endif
337
338 #ifdef RT_USING_UART2
339 serial = &serial2;
340
341 serial->parent.type = RT_Device_Class_Char;
342
343 serial->hw_base = 0xE0010000;
344 serial->baudrate = 115200;
345
346 rt_memset(serial->rx_buffer, 0, sizeof(serial->rx_buffer));
347 serial->read_index = serial->save_index = 0;
348
349 serial->parent.init = rt_serial_init;
350 serial->parent.open = rt_serial_open;
351 serial->parent.close = rt_serial_close;
352 serial->parent.read = rt_serial_read;
353 serial->parent.write = rt_serial_write;
354 serial->parent.control = rt_serial_control;
355 serial->parent.user_data = RT_NULL;
356
357 rt_device_register(&serial->parent,
358 "uart2", RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX);
359 #endif
360 }
361
362 /*@}*/
363