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 */
rt_serial_init(rt_device_t dev)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
rt_serial_open(rt_device_t dev,rt_uint16_t oflag)56 static rt_err_t rt_serial_open(rt_device_t dev, rt_uint16_t oflag)
57 {
58 return RT_EOK;
59 }
60
rt_serial_close(rt_device_t dev)61 static rt_err_t rt_serial_close(rt_device_t dev)
62 {
63 return RT_EOK;
64 }
65
rt_serial_read(rt_device_t dev,rt_off_t pos,void * buffer,rt_size_t size)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
rt_serial_write(rt_device_t dev,rt_off_t pos,const void * buffer,rt_size_t size)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
rt_serial_control(rt_device_t dev,int cmd,void * args)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 */
rt_hw_serial_register(rt_device_t device,const char * name,rt_uint32_t flag,struct avr32_serial_device * serial)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 */
rt_hw_serial_isr(void)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