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 * 2006-08-23 Bernard first version
13 * 2009-05-14 Bernard add RT-THread device interface
14 *
15 * 2011-12-17 nl1031 MicroBlaze
16 */
17
18 #include <rthw.h>
19 #include <rtthread.h>
20 #include "serial.h"
21
22 typedef volatile rt_uint32_t REG32;
23 struct rt_mb_uart_lite_hw
24 {
25 REG32 Rx_FIFO; // Receiver Holding Register
26 REG32 Tx_FIFO; // Transmitter Holding Register
27 REG32 STAT_REG; // Channel Status Register
28 REG32 CTRL_REG; // Control Register
29 };
30
31 struct rt_mb_uart_lite
32 {
33 struct rt_device parent;
34
35 struct rt_mb_uart_lite_hw* hw_base;
36 rt_uint16_t peripheral_id;
37 rt_uint32_t baudrate;
38
39 /* reception field */
40 rt_uint16_t save_index, read_index;
41 rt_uint8_t rx_buffer[RT_UART_RX_BUFFER_SIZE];
42 };
43 #ifdef RT_USING_UART1
44 struct rt_mb_uart_lite serial1;
45 #endif
46
rt_hw_serial_isr(void)47 static void rt_hw_serial_isr(void)
48 {
49 unsigned int status;
50 rt_base_t level;
51 struct rt_device* device;
52 struct rt_mb_uart_lite* serial = RT_NULL;
53
54 #ifdef RT_USING_UART1
55 /* serial 1 */
56 serial = &serial1;
57 #endif
58 RT_ASSERT(serial != RT_NULL);
59
60 /* get generic device object */
61 device = (rt_device_t)serial;
62
63 /* disable interrupt */
64 level = rt_hw_interrupt_disable();
65
66 /* get uart status register */
67 status = serial->hw_base->STAT_REG;
68 while (status & XUL_SR_RX_FIFO_VALID_DATA)
69 {
70 /* get received character */
71 serial->rx_buffer[serial->save_index] = serial->hw_base->Rx_FIFO;
72
73 /* move to next position */
74 serial->save_index ++;
75 if (serial->save_index >= RT_UART_RX_BUFFER_SIZE)
76 serial->save_index = 0;
77
78 /* if the next position is read index, discard this 'read char' */
79 if (serial->save_index == serial->read_index)
80 {
81 serial->read_index ++;
82 if (serial->read_index >= RT_UART_RX_BUFFER_SIZE)
83 serial->read_index = 0;
84 }
85 status = serial->hw_base->STAT_REG;
86 }
87 /* enable interrupt */
88 rt_hw_interrupt_enable(level);
89
90 /* indicate to upper layer application */
91 if (device->rx_indicate != RT_NULL)
92 device->rx_indicate(device, 1);
93
94 }
95
rt_serial_init(rt_device_t dev)96 static rt_err_t rt_serial_init (rt_device_t dev)
97 {
98 struct rt_mb_uart_lite* serial = (struct rt_mb_uart_lite*) dev;
99
100 RT_ASSERT(serial != RT_NULL);
101
102 RT_ASSERT(serial->peripheral_id != XPAR_UARTLITE_1_DEVICE_ID);
103
104
105 /* reset rx index */
106 serial->save_index = 0;
107 serial->read_index = 0;
108
109 /* reset rx buffer */
110 rt_memset(serial->rx_buffer, 0, RT_UART_RX_BUFFER_SIZE);
111
112 return RT_EOK;
113 }
114
rt_serial_open(rt_device_t dev,rt_uint16_t oflag)115 static rt_err_t rt_serial_open(rt_device_t dev, rt_uint16_t oflag)
116 {
117 struct rt_mb_uart_lite *serial = (struct rt_mb_uart_lite*)dev;
118 RT_ASSERT(serial != RT_NULL);
119
120 if (dev->flag & RT_DEVICE_FLAG_INT_RX)
121 {
122 /* enable UART rx interrupt */
123 serial->hw_base->CTRL_REG = XUL_CR_ENABLE_INTR; /* enable interrupt */
124
125 /* install UART handler */
126 rt_hw_interrupt_install(serial->peripheral_id, (rt_isr_handler_t)rt_hw_serial_isr, RT_NULL);
127 rt_hw_interrupt_umask(serial->peripheral_id);
128 }
129
130 return RT_EOK;
131 }
132
rt_serial_close(rt_device_t dev)133 static rt_err_t rt_serial_close(rt_device_t dev)
134 {
135 struct rt_mb_uart_lite *serial = (struct rt_mb_uart_lite*)dev;
136 RT_ASSERT(serial != RT_NULL);
137
138 if (dev->flag & RT_DEVICE_FLAG_INT_RX)
139 {
140 /* disable interrupt */
141 serial->hw_base->CTRL_REG = 0; /* RxReady interrupt */
142 }
143
144 return RT_EOK;
145 }
146
rt_serial_read(rt_device_t dev,rt_off_t pos,void * buffer,rt_size_t size)147 static rt_size_t rt_serial_read (rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size)
148 {
149 rt_uint8_t* ptr;
150 struct rt_mb_uart_lite *serial = (struct rt_mb_uart_lite*)dev;
151 RT_ASSERT(serial != RT_NULL);
152
153 /* point to buffer */
154 ptr = (rt_uint8_t*) buffer;
155
156 if (dev->flag & RT_DEVICE_FLAG_INT_RX)
157 {
158 while (size)
159 {
160 /* interrupt receive */
161 rt_base_t level;
162
163 /* disable interrupt */
164 level = rt_hw_interrupt_disable();
165 if (serial->read_index != serial->save_index)
166 {
167 *ptr = serial->rx_buffer[serial->read_index];
168
169 serial->read_index ++;
170 if (serial->read_index >= RT_UART_RX_BUFFER_SIZE)
171 serial->read_index = 0;
172 }
173 else
174 {
175 /* no data in rx buffer */
176
177 /* enable interrupt */
178 rt_hw_interrupt_enable(level);
179 break;
180 }
181
182 /* enable interrupt */
183 rt_hw_interrupt_enable(level);
184
185 ptr ++; size --;
186 }
187
188 return (rt_uint32_t)ptr - (rt_uint32_t)buffer;
189 }
190 else if (dev->flag & RT_DEVICE_FLAG_DMA_RX)
191 {
192 /* not support right now */
193 RT_ASSERT(0);
194 }
195 else
196 {
197 /* poll mode */
198 while (size)
199 {
200 /* Wait for Full Rx Buffer */
201 while (!(serial->hw_base->STAT_REG & XUL_SR_RX_FIFO_VALID_DATA));
202
203 /* Read Character */
204 *ptr = serial->hw_base->Rx_FIFO;
205 ptr ++;
206 size --;
207 }
208
209 return (rt_size_t)ptr - (rt_size_t)buffer;
210 }
211
212 return 0;
213 }
214
rt_serial_write(rt_device_t dev,rt_off_t pos,const void * buffer,rt_size_t size)215 static rt_size_t rt_serial_write (rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size)
216 {
217 rt_uint8_t* ptr;
218 struct rt_mb_uart_lite *serial = (struct rt_mb_uart_lite*)dev;
219 RT_ASSERT(serial != RT_NULL);
220
221 ptr = (rt_uint8_t*) buffer;
222 if (dev->open_flag & RT_DEVICE_OFLAG_WRONLY)
223 {
224 if (dev->flag & RT_DEVICE_FLAG_STREAM)
225 {
226 /* it's a stream mode device */
227 while (size)
228 {
229 /* stream mode */
230 if (*ptr == '\n')
231 {
232 while (!(serial->hw_base->STAT_REG & XUL_SR_TX_FIFO_EMPTY));
233 serial->hw_base->Tx_FIFO = '\r';
234 }
235
236 /* Wait for Empty Tx Buffer */
237 while (!(serial->hw_base->STAT_REG & XUL_SR_TX_FIFO_EMPTY));
238
239 /* Transmit Character */
240 serial->hw_base->Tx_FIFO = *ptr;
241 if (*ptr & 1)
242 rt_hw_board_led_on(2);
243 else
244 rt_hw_board_led_off(2);
245 ptr ++; size --;
246 }
247 }
248 else
249 {
250 while (size)
251 {
252 /* Wait for Empty Tx Buffer */
253 while (!(serial->hw_base->STAT_REG & XUL_SR_TX_FIFO_EMPTY));
254
255 /* Transmit Character */
256 serial->hw_base->Tx_FIFO = *ptr;
257 if (*ptr & 1)
258 rt_hw_board_led_on(2);
259 else
260 rt_hw_board_led_off(2);
261 ptr ++; size --;
262 }
263 }
264 }
265
266 return (rt_size_t)ptr - (rt_size_t)buffer;
267 }
268
rt_serial_control(rt_device_t dev,int cmd,void * args)269 static rt_err_t rt_serial_control (rt_device_t dev, int cmd, void *args)
270 {
271 return RT_EOK;
272 }
273
rt_hw_serial_init()274 rt_err_t rt_hw_serial_init()
275 {
276 rt_device_t device;
277
278 #ifndef RT_USING_CONSOLE
279 int Status;
280
281 /*
282 * Initialize the UartLite driver so that it is ready to use.
283 */
284 Status = XUartLite_Initialize(&uart_lite, RS232_DEVICE_ID);
285 if (Status != XST_SUCCESS)
286 {
287 return;
288 }
289
290 #endif
291
292 #ifdef RT_USING_UART1
293 device = (rt_device_t) &serial1;
294
295 /* init serial device private data */
296 serial1.hw_base = (struct rt_mb_uart_lite_hw*)XPAR_USB_UART_BASEADDR;
297 serial1.peripheral_id = XPAR_UARTLITE_1_DEVICE_ID;
298 serial1.baudrate = 115200;
299
300 /* set device virtual interface */
301 device->init = rt_serial_init;
302 device->open = rt_serial_open;
303 device->close = rt_serial_close;
304 device->read = rt_serial_read;
305 device->write = rt_serial_write;
306 device->control = rt_serial_control;
307
308 /* register uart1 on device subsystem */
309 rt_device_register(device, "uart1", RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX);
310 #endif
311
312
313 return RT_EOK;
314 }
315
316
317