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