xref: /nrf52832-nimble/rt-thread/libcpu/avr32/uc3/serial.c (revision 042d53a763ad75cb1465103098bb88c245d95138)
1 /*
2  * File      : serial.c
3  * This file is part of RT-Thread RTOS
4  * COPYRIGHT (C) 2010, 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://www.rt-thread.org/license/LICENSE
9  *
10  * Change Logs:
11  * Date           Author       Notes
12  * 2009-02-05     Bernard      first version
13  * 2009-10-25     Bernard      fix rt_serial_read bug when there is no data
14  *                             in the buffer.
15  * 2010-03-29     Bernard      cleanup code.
16  * 2010-03-30     Kyle         Ported from STM32 to AVR32.
17  */
18 
19 #include "serial.h"
20 #include "compiler.h"
21 #include "usart.h"
22 
23 struct rt_device _rt_usart_device;
24 struct avr32_serial_int_rx _rt_usart_rx;
25 struct avr32_serial_device uart =
26 {
27 	.uart_device = (avr32_usart_t *) &AVR32_USART1,
28 	.int_rx = &_rt_usart_rx
29 };
30 
31 /**
32  * @addtogroup AVR32UC3
33  */
34 /*@{*/
35 
36 /* RT-Thread Device Interface */
37 static rt_err_t rt_serial_init (rt_device_t dev)
38 {
39 	struct avr32_serial_device* uart = (struct avr32_serial_device*) dev->user_data;
40 
41 	if (!(dev->flag & RT_DEVICE_FLAG_ACTIVATED))
42 	{
43 		if (dev->flag & RT_DEVICE_FLAG_INT_RX)
44 		{
45 			rt_memset(uart->int_rx->rx_buffer, 0, sizeof(uart->int_rx->rx_buffer));
46 			uart->int_rx->read_index = 0;
47 			uart->int_rx->save_index = 0;
48 		}
49 
50 		dev->flag |= RT_DEVICE_FLAG_ACTIVATED;
51 	}
52 
53 	return RT_EOK;
54 }
55 
56 static rt_err_t rt_serial_open(rt_device_t dev, rt_uint16_t oflag)
57 {
58 	return RT_EOK;
59 }
60 
61 static rt_err_t rt_serial_close(rt_device_t dev)
62 {
63 	return RT_EOK;
64 }
65 
66 static rt_size_t rt_serial_read (rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size)
67 {
68 	rt_uint8_t* ptr;
69 	rt_err_t err_code;
70 	struct avr32_serial_device* uart;
71 
72 	ptr = buffer;
73 	err_code = RT_EOK;
74 	uart = (struct avr32_serial_device*)dev->user_data;
75 
76 	if (dev->flag & RT_DEVICE_FLAG_INT_RX)
77 	{
78 		/* interrupt mode Rx */
79 		while (size)
80 		{
81 			rt_base_t level;
82 
83 			/* disable interrupt */
84 			level = rt_hw_interrupt_disable();
85 
86 			if (uart->int_rx->read_index != uart->int_rx->save_index)
87 			{
88 				/* read a character */
89 				*ptr++ = uart->int_rx->rx_buffer[uart->int_rx->read_index];
90 				size--;
91 
92 				/* move to next position */
93 				uart->int_rx->read_index ++;
94 				if (uart->int_rx->read_index >= UART_RX_BUFFER_SIZE)
95 					uart->int_rx->read_index = 0;
96 			}
97 			else
98 			{
99 				/* set error code */
100 				err_code = -RT_EEMPTY;
101 
102 				/* enable interrupt */
103 				rt_hw_interrupt_enable(level);
104 				break;
105 			}
106 
107 			/* enable interrupt */
108 			rt_hw_interrupt_enable(level);
109 		}
110 	}
111 	else
112 	{
113 		/* polling mode */
114 		while ((rt_uint32_t)ptr - (rt_uint32_t)buffer < size)
115 		{
116 			while (usart_test_hit(uart->uart_device))
117 			{
118 				*ptr = uart->uart_device->rhr & 0xff;
119 				ptr ++;
120 			}
121 		}
122 	}
123 
124 	/* set error code */
125 	rt_set_errno(err_code);
126 	return (rt_uint32_t)ptr - (rt_uint32_t)buffer;
127 }
128 
129 static rt_size_t rt_serial_write (rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size)
130 {
131 	rt_uint8_t* ptr;
132 	rt_err_t err_code;
133 	struct avr32_serial_device* uart;
134 
135 	err_code = RT_EOK;
136 	ptr = (rt_uint8_t*)buffer;
137 	uart = (struct avr32_serial_device*)dev->user_data;
138 
139 	if (dev->flag & RT_DEVICE_FLAG_INT_TX)
140 	{
141 		/* interrupt mode Tx, does not support */
142 		RT_ASSERT(0);
143 	}
144 	else
145 	{
146 		/* polling mode */
147 		if (dev->flag & RT_DEVICE_FLAG_STREAM)
148 		{
149 			/* stream mode */
150 			while (size)
151 			{
152 				usart_putchar(uart->uart_device, (int) *ptr);
153 
154 				++ptr; --size;
155 			}
156 		}
157 		else
158 		{
159 			/* write data directly */
160 			while (size)
161 			{
162 				usart_bw_write_char(uart->uart_device, (int) *ptr);
163 
164 				++ptr; --size;
165 			}
166 		}
167 	}
168 
169 	/* set error code */
170 	rt_set_errno(err_code);
171 
172 	return (rt_uint32_t)ptr - (rt_uint32_t)buffer;
173 }
174 
175 static rt_err_t rt_serial_control (rt_device_t dev, int cmd, void *args)
176 {
177 	struct avr32_serial_device* uart;
178 
179 	RT_ASSERT(dev != RT_NULL);
180 
181 	uart = (struct avr32_serial_device*)dev->user_data;
182 	switch (cmd)
183 	{
184 	case RT_DEVICE_CTRL_SUSPEND:
185 		/* suspend device */
186 		dev->flag |= RT_DEVICE_FLAG_SUSPENDED;
187 		break;
188 
189 	case RT_DEVICE_CTRL_RESUME:
190 		/* resume device */
191 		dev->flag &= ~RT_DEVICE_FLAG_SUSPENDED;
192 		break;
193 	}
194 
195 	return RT_EOK;
196 }
197 
198 /*
199  * serial register for STM32
200  * support STM32F103VB and STM32F103ZE
201  */
202 rt_err_t rt_hw_serial_register(rt_device_t device, const char* name, rt_uint32_t flag, struct avr32_serial_device *serial)
203 {
204 	RT_ASSERT(device != RT_NULL);
205 
206 	if ((flag & RT_DEVICE_FLAG_DMA_RX) ||
207 		(flag & RT_DEVICE_FLAG_INT_TX))
208 	{
209 		RT_ASSERT(0);
210 	}
211 
212 	device->type 		= RT_Device_Class_Char;
213 	device->rx_indicate = RT_NULL;
214 	device->tx_complete = RT_NULL;
215 	device->init 		= rt_serial_init;
216 	device->open		= rt_serial_open;
217 	device->close		= rt_serial_close;
218 	device->read 		= rt_serial_read;
219 	device->write 		= rt_serial_write;
220 	device->control 	= rt_serial_control;
221 	device->user_data	= serial;
222 
223 	/* register a character device */
224 	return rt_device_register(device, name, RT_DEVICE_FLAG_RDWR | flag);
225 }
226 
227 /* ISR for serial interrupt */
228 void rt_hw_serial_isr(void)
229 {
230 	struct avr32_serial_device* uart = (struct avr32_serial_device*) _rt_usart_device.user_data;
231 	rt_base_t level;
232 
233 	if (usart_test_hit(uart->uart_device))
234 	{
235 		/* interrupt mode receive */
236 		RT_ASSERT(device->flag & RT_DEVICE_FLAG_INT_RX);
237 
238 		/* disable interrupt */
239 		level = rt_hw_interrupt_disable();
240 
241 		/* save character */
242 		uart->int_rx->rx_buffer[uart->int_rx->save_index] = uart->uart_device->rhr & 0xff;
243 		uart->int_rx->save_index ++;
244 		if (uart->int_rx->save_index >= UART_RX_BUFFER_SIZE)
245 			uart->int_rx->save_index = 0;
246 
247 		/* if the next position is read index, discard this 'read char' */
248 		if (uart->int_rx->save_index == uart->int_rx->read_index)
249 		{
250 			uart->int_rx->read_index ++;
251 			if (uart->int_rx->read_index >= UART_RX_BUFFER_SIZE)
252 				uart->int_rx->read_index = 0;
253 		}
254 
255 		/* enable interrupt */
256 		rt_hw_interrupt_enable(level);
257 
258 		/* invoke callback */
259 		if (_rt_usart_device.rx_indicate != RT_NULL)
260 		{
261 			rt_size_t rx_length;
262 
263 			/* get rx length */
264 			rx_length = uart->int_rx->read_index > uart->int_rx->save_index ?
265 				UART_RX_BUFFER_SIZE - uart->int_rx->read_index + uart->int_rx->save_index :
266 				uart->int_rx->save_index - uart->int_rx->read_index;
267 
268 			_rt_usart_device.rx_indicate(&_rt_usart_device, rx_length);
269 		}
270 	}
271 	else
272 	{
273 		usart_reset_status(uart->uart_device);
274 	}
275 }
276 
277 /*@}*/
278