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