xref: /nrf52832-nimble/rt-thread/libcpu/blackfin/bf53x/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-03-13     Bernard      first version
13  * 2009-04-20     yi.qiu       modified according bernard's stm32 version
14  * 2012-02-17     mojingxian   modified for bf53x
15  */
16 
17 #include <rtthread.h>
18 
19 #include "serial.h"
20 
21 /**
22  * @addtogroup BF53X
23  */
24 /*@{*/
25 
26 /* RT-Thread Device Interface */
27 /**
28  * This function initializes serial
29  */
rt_serial_init(rt_device_t dev)30 static rt_err_t rt_serial_init (rt_device_t dev)
31 {
32 	struct serial_device* uart = (struct serial_device*) dev->user_data;
33 
34 	if (!(dev->flag & RT_DEVICE_FLAG_ACTIVATED))
35 	{
36 
37 		if (dev->flag & RT_DEVICE_FLAG_INT_RX)
38 		{
39 			rt_memset(uart->int_rx->rx_buffer, 0,
40 				sizeof(uart->int_rx->rx_buffer));
41 			uart->int_rx->read_index = uart->int_rx->save_index = 0;
42 		}
43 
44 		if (dev->flag & RT_DEVICE_FLAG_INT_TX)
45 		{
46 			rt_memset(uart->int_tx->tx_buffer, 0,
47 				sizeof(uart->int_tx->tx_buffer));
48 			uart->int_tx->write_index = uart->int_tx->save_index = 0;
49 		}
50 
51 		dev->flag |= RT_DEVICE_FLAG_ACTIVATED;
52 	}
53 
54 	return RT_EOK;
55 }
56 
57 /* save a char to serial buffer */
rt_serial_savechar(struct serial_device * uart,char ch)58 static void rt_serial_savechar(struct serial_device* uart, char ch)
59 {
60 	rt_base_t level;
61 
62 	/* disable interrupt */
63 	level = rt_hw_interrupt_disable();
64 
65 	uart->int_rx->rx_buffer[uart->int_rx->save_index] = ch;
66 	uart->int_rx->save_index ++;
67 	if (uart->int_rx->save_index >= UART_RX_BUFFER_SIZE)
68 		uart->int_rx->save_index = 0;
69 
70 	/* if the next position is read index, discard this 'read char' */
71 	if (uart->int_rx->save_index == uart->int_rx->read_index)
72 	{
73 		uart->int_rx->read_index ++;
74 		if (uart->int_rx->read_index >= UART_RX_BUFFER_SIZE)
75 			uart->int_rx->read_index = 0;
76 	}
77 
78 	/* enable interrupt */
79 	rt_hw_interrupt_enable(level);
80 }
81 
rt_serial_open(rt_device_t dev,rt_uint16_t oflag)82 static rt_err_t rt_serial_open(rt_device_t dev, rt_uint16_t oflag)
83 {
84 	RT_ASSERT(dev != RT_NULL);
85 
86 	return RT_EOK;
87 }
88 
rt_serial_close(rt_device_t dev)89 static rt_err_t rt_serial_close(rt_device_t dev)
90 {
91 	RT_ASSERT(dev != RT_NULL);
92 
93 	return RT_EOK;
94 }
95 
rt_serial_read(rt_device_t dev,rt_off_t pos,void * buffer,rt_size_t size)96 static rt_size_t rt_serial_read (rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size)
97 {
98 	rt_uint8_t* ptr;
99 	rt_err_t err_code;
100 	struct serial_device* uart;
101 
102 	ptr = buffer;
103 	err_code = RT_EOK;
104 	uart = (struct serial_device*)dev->user_data;
105 
106 	if (dev->flag & RT_DEVICE_FLAG_INT_RX)
107 	{
108 		rt_base_t level;
109 
110 		/* interrupt mode Rx */
111 		while (size)
112 		{
113 			if (uart->int_rx->read_index != uart->int_rx->save_index)
114 			{
115 				*ptr++ = uart->int_rx->rx_buffer[uart->int_rx->read_index];
116 				size --;
117 
118 				/* disable interrupt */
119 				level = rt_hw_interrupt_disable();
120 
121 				uart->int_rx->read_index ++;
122 				if (uart->int_rx->read_index >= UART_RX_BUFFER_SIZE)
123 					uart->int_rx->read_index = 0;
124 
125 				/* enable interrupt */
126 				rt_hw_interrupt_enable(level);
127 			}
128 			else
129 			{
130 				/* set error code */
131 				err_code = -RT_EEMPTY;
132 				break;
133 			}
134 		}
135 	}
136 	else
137 	{
138 		/* polling mode */
139 		while ((rt_uint32_t)ptr - (rt_uint32_t)buffer < size)
140 		{
141 			//while (uart->uart_device->ustat & USTAT_RCV_READY)
142 			{
143 				*ptr = uart->uart_device->rbr_thr & 0xff;
144 				ptr ++;
145 			}
146 		}
147 	}
148 
149 	/* set error code */
150 	rt_set_errno(err_code);
151 	return (rt_uint32_t)ptr - (rt_uint32_t)buffer;
152 }
153 
rt_serial_write(rt_device_t dev,rt_off_t pos,const void * buffer,rt_size_t size)154 static rt_size_t rt_serial_write (rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size)
155 {
156 	rt_uint8_t* ptr;
157 	rt_err_t err_code;
158 	struct serial_device* uart;
159 
160 	err_code = RT_EOK;
161 	ptr = (rt_uint8_t*)buffer;
162 	uart = (struct serial_device*)dev->user_data;
163 
164 	if (dev->flag & RT_DEVICE_FLAG_INT_TX)
165 	{
166 		/* interrupt mode Tx */
167 		while (uart->int_tx->save_index != uart->int_tx->write_index)
168 		{
169 			/* save on tx buffer */
170 			uart->int_tx->tx_buffer[uart->int_tx->save_index] = *ptr++;
171 
172 			-- size;
173 
174 			/* move to next position */
175 			uart->int_tx->save_index ++;
176 
177 			/* wrap save index */
178 			if (uart->int_tx->save_index >= UART_TX_BUFFER_SIZE)
179 				uart->int_tx->save_index = 0;
180 		}
181 
182 		/* set error code */
183 		if (size > 0)
184 			err_code = -RT_EFULL;
185 	}
186 	else
187 	{
188 		/* polling mode */
189 		while (size)
190 		{
191 			/*
192 			 * to be polite with serial console add a line feed
193 			 * to the carriage return character
194 			 */
195 			if (*ptr == '\n' && (dev->flag & RT_DEVICE_FLAG_STREAM))
196 			{
197 				while (!(uart->uart_device->lsr & 0x20));
198 				uart->uart_device->rbr_thr = '\r';
199 			}
200 
201 			while (!(uart->uart_device->lsr & 0x20));
202 			uart->uart_device->rbr_thr = (*ptr & 0xFF);
203 
204 			++ptr; --size;
205 		}
206 	}
207 
208 	/* set error code */
209 	rt_set_errno(err_code);
210 
211 	return (rt_uint32_t)ptr - (rt_uint32_t)buffer;
212 }
213 
rt_serial_control(rt_device_t dev,int cmd,void * args)214 static rt_err_t rt_serial_control (rt_device_t dev, int cmd, void *args)
215 {
216 	RT_ASSERT(dev != RT_NULL);
217 
218 	switch (cmd)
219 	{
220 	case RT_DEVICE_CTRL_SUSPEND:
221 		/* suspend device */
222 		dev->flag |= RT_DEVICE_FLAG_SUSPENDED;
223 		break;
224 
225 	case RT_DEVICE_CTRL_RESUME:
226 		/* resume device */
227 		dev->flag &= ~RT_DEVICE_FLAG_SUSPENDED;
228 		break;
229 	}
230 
231 	return RT_EOK;
232 }
233 
234 /*
235  * serial register
236  */
rt_hw_serial_register(rt_device_t device,const char * name,rt_uint32_t flag,struct serial_device * serial)237 rt_err_t rt_hw_serial_register(rt_device_t device, const char* name, rt_uint32_t flag, struct serial_device *serial)
238 {
239 	RT_ASSERT(device != RT_NULL);
240 
241 	device->type 		= RT_Device_Class_Char;
242 	device->rx_indicate = RT_NULL;
243 	device->tx_complete = RT_NULL;
244 	device->init 		= rt_serial_init;
245 	device->open		= rt_serial_open;
246 	device->close		= rt_serial_close;
247 	device->read 		= rt_serial_read;
248 	device->write 		= rt_serial_write;
249 	device->control 	= rt_serial_control;
250 	device->user_data   = serial;
251 
252 	/* register a character device */
253 	return rt_device_register(device, name, RT_DEVICE_FLAG_RDWR | flag);
254 }
255 
256 /* ISR for serial interrupt */
rt_hw_serial_isr(rt_device_t device)257 void rt_hw_serial_isr(rt_device_t device)
258 {
259 	struct serial_device* uart = (struct serial_device*) device->user_data;
260 
261 	/* interrupt mode receive */
262 	RT_ASSERT(device->flag & RT_DEVICE_FLAG_INT_RX);
263 
264 	/* save on rx buffer */
265 	//while (uart->uart_device->ustat & USTAT_RCV_READY)
266 	{
267 		rt_serial_savechar(uart, uart->uart_device->rbr_thr & 0xff);
268 	}
269 
270 	/* invoke callback */
271 	if (device->rx_indicate != RT_NULL)
272 	{
273 		rt_size_t rx_length;
274 
275 		/* get rx length */
276 		rx_length = uart->int_rx->read_index > uart->int_rx->save_index ?
277 			UART_RX_BUFFER_SIZE - uart->int_rx->read_index + uart->int_rx->save_index :
278 			uart->int_rx->save_index - uart->int_rx->read_index;
279 
280 		device->rx_indicate(device, rx_length);
281 	}
282 }
283 
284 /*@}*/
285