xref: /nrf52832-nimble/rt-thread/libcpu/xilinx/microblaze/serial.c (revision 104654410c56c573564690304ae786df310c91fc)
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