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