1 /*
2 * Copyright (c) 2006-2021, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2006-08-23 Bernard first version
9 */
10
11 #include <rthw.h>
12 #include <rtthread.h>
13
14 #include "lpc214x.h"
15 #include "board.h"
16
17 /* serial hardware register */
18 #define REG8(d) (*((volatile unsigned char *)(d)))
19 #define REG32(d) (*((volatile unsigned long *)(d)))
20
21 #define UART_RBR(base) REG8(base + 0x00)
22 #define UART_THR(base) REG8(base + 0x00)
23 #define UART_IER(base) REG32(base + 0x04)
24 #define UART_IIR(base) REG32(base + 0x08)
25 #define UART_FCR(base) REG8(base + 0x08)
26 #define UART_LCR(base) REG8(base + 0x0C)
27 #define UART_MCR(base) REG8(base + 0x10)
28 #define UART_LSR(base) REG8(base + 0x14)
29 #define UART_MSR(base) REG8(base + 0x18)
30 #define UART_SCR(base) REG8(base + 0x1C)
31 #define UART_DLL(base) REG8(base + 0x00)
32 #define UART_DLM(base) REG8(base + 0x04)
33 #define UART_ACR(base) REG32(base + 0x20)
34 #define UART_FDR(base) REG32(base + 0x28)
35 #define UART_TER(base) REG8(base + 0x30)
36
37 /* LPC serial device */
38 struct rt_lpcserial
39 {
40 /* inherit from device */
41 struct rt_device parent;
42
43 rt_uint32_t hw_base;
44 rt_uint32_t irqno;
45 rt_uint32_t baudrate;
46
47 /* reception field */
48 rt_uint16_t save_index, read_index;
49 rt_uint8_t rx_buffer[RT_UART_RX_BUFFER_SIZE];
50 };
51
52 #ifdef RT_USING_UART1
53 struct rt_lpcserial serial1;
54 #endif
55 #ifdef RT_USING_UART2
56 struct rt_lpcserial serial2;
57 #endif
58
59 void rt_hw_serial_init(void);
60
61 #define U0PINS 0x00000005
62
rt_hw_uart_isr(struct rt_lpcserial * lpc_serial)63 void rt_hw_uart_isr(struct rt_lpcserial* lpc_serial)
64 {
65 rt_uint32_t iir;
66
67 RT_ASSERT(lpc_serial != RT_NULL)
68
69 RT_UNUSED(iir);
70
71 if (UART_LSR(lpc_serial->hw_base) & 0x01)
72 {
73 rt_base_t level;
74
75 while (UART_LSR(lpc_serial->hw_base) & 0x01)
76 {
77 /* disable interrupt */
78 level = rt_hw_interrupt_disable();
79
80 /* read character */
81 lpc_serial->rx_buffer[lpc_serial->save_index] =
82 UART_RBR(lpc_serial->hw_base);
83 lpc_serial->save_index ++;
84 if (lpc_serial->save_index >= RT_UART_RX_BUFFER_SIZE)
85 lpc_serial->save_index = 0;
86
87 /* if the next position is read index, discard this 'read char' */
88 if (lpc_serial->save_index == lpc_serial->read_index)
89 {
90 lpc_serial->read_index ++;
91 if (lpc_serial->read_index >= RT_UART_RX_BUFFER_SIZE)
92 lpc_serial->read_index = 0;
93 }
94
95 /* enable interrupt */
96 rt_hw_interrupt_enable(level);
97 }
98
99 /* invoke callback */
100 if(lpc_serial->parent.rx_indicate != RT_NULL)
101 {
102 lpc_serial->parent.rx_indicate(&lpc_serial->parent, 1);
103 }
104 }
105
106 /* clear interrupt source */
107 iir = UART_IIR(lpc_serial->hw_base);
108
109 /* acknowledge Interrupt */
110 VICVectAddr = 0;
111 }
112
113 #ifdef RT_USING_UART1
rt_hw_uart_isr_1(int irqno,void * param)114 void rt_hw_uart_isr_1(int irqno, void *param)
115 {
116 /* get lpc serial device */
117 rt_hw_uart_isr(&serial1);
118 }
119 #endif
120
121 #ifdef RT_USING_UART2
rt_hw_uart_isr_2(int irqno,void * param)122 void rt_hw_uart_isr_2(int irqno, void *param)
123 {
124 /* get lpc serial device */
125 rt_hw_uart_isr(&serial2);
126 }
127 #endif
128
129 /**
130 * @addtogroup LPC214x
131 */
132 /*@{*/
133
rt_serial_init(rt_device_t dev)134 static rt_err_t rt_serial_init (rt_device_t dev)
135 {
136 return RT_EOK;
137 }
138
rt_serial_open(rt_device_t dev,rt_uint16_t oflag)139 static rt_err_t rt_serial_open(rt_device_t dev, rt_uint16_t oflag)
140 {
141 struct rt_lpcserial* lpc_serial;
142 lpc_serial = (struct rt_lpcserial*) dev;
143
144 RT_ASSERT(lpc_serial != RT_NULL);
145 if (dev->flag & RT_DEVICE_FLAG_INT_RX)
146 {
147 /* init UART rx interrupt */
148 UART_IER(lpc_serial->hw_base) = 0x01;
149
150 /* install ISR */
151 if (lpc_serial->irqno == UART0_INT)
152 {
153 #ifdef RT_USING_UART1
154 rt_hw_interrupt_install(lpc_serial->irqno,
155 rt_hw_uart_isr_1, &serial1, "UART1");
156 #endif
157 }
158 else
159 {
160 #ifdef RT_USING_UART2
161 rt_hw_interrupt_install(lpc_serial->irqno,
162 rt_hw_uart_isr_2, &serial2, "UART2");
163 #endif
164 }
165
166 rt_hw_interrupt_umask(lpc_serial->irqno);
167 }
168
169 return RT_EOK;
170 }
171
rt_serial_close(rt_device_t dev)172 static rt_err_t rt_serial_close(rt_device_t dev)
173 {
174 struct rt_lpcserial* lpc_serial;
175 lpc_serial = (struct rt_lpcserial*) dev;
176
177 RT_ASSERT(lpc_serial != RT_NULL);
178
179 if (dev->flag & RT_DEVICE_FLAG_INT_RX)
180 {
181 /* disable UART rx interrupt */
182 UART_IER(lpc_serial->hw_base) = 0x00;
183 }
184
185 return RT_EOK;
186 }
187
rt_serial_control(rt_device_t dev,int cmd,void * args)188 static rt_err_t rt_serial_control(rt_device_t dev, int cmd, void *args)
189 {
190 return RT_EOK;
191 }
192
rt_serial_read(rt_device_t dev,rt_off_t pos,void * buffer,rt_size_t size)193 static rt_ssize_t rt_serial_read(rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size)
194 {
195 rt_uint8_t* ptr;
196 struct rt_lpcserial *lpc_serial = (struct rt_lpcserial*)dev;
197 RT_ASSERT(lpc_serial != RT_NULL);
198
199 /* point to buffer */
200 ptr = (rt_uint8_t*) buffer;
201
202 if (dev->flag & RT_DEVICE_FLAG_INT_RX)
203 {
204 while (size)
205 {
206 /* interrupt receive */
207 rt_base_t level;
208
209 /* disable interrupt */
210 level = rt_hw_interrupt_disable();
211 if (lpc_serial->read_index != lpc_serial->save_index)
212 {
213 *ptr = lpc_serial->rx_buffer[lpc_serial->read_index];
214
215 lpc_serial->read_index ++;
216 if (lpc_serial->read_index >= RT_UART_RX_BUFFER_SIZE)
217 lpc_serial->read_index = 0;
218 }
219 else
220 {
221 /* no data in rx buffer */
222
223 /* enable interrupt */
224 rt_hw_interrupt_enable(level);
225 break;
226 }
227
228 /* enable interrupt */
229 rt_hw_interrupt_enable(level);
230
231 ptr ++; size --;
232 }
233
234 return (rt_uint32_t)ptr - (rt_uint32_t)buffer;
235 }
236 else if (dev->flag & RT_DEVICE_FLAG_DMA_RX)
237 {
238 /* not support right now */
239 RT_ASSERT(0);
240 }
241
242 /* polling mode */
243 while (size && (UART_LSR(lpc_serial->hw_base) & 0x01))
244 {
245 /* Read Character */
246 *ptr = UART_RBR(lpc_serial->hw_base);
247
248 ptr ++;
249 size --;
250 }
251
252 return (rt_size_t)ptr - (rt_size_t)buffer;
253 }
254
rt_serial_write(rt_device_t dev,rt_off_t pos,const void * buffer,rt_size_t size)255 static rt_ssize_t rt_serial_write(rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size)
256 {
257 struct rt_lpcserial* lpc_serial;
258 char *ptr;
259
260 lpc_serial = (struct rt_lpcserial*) dev;
261 if (dev->flag & RT_DEVICE_FLAG_INT_TX)
262 {
263 /* not support */
264 RT_ASSERT(0);
265 }
266 else if (dev->flag & RT_DEVICE_FLAG_DMA_TX)
267 {
268 /* not support */
269 RT_ASSERT(0);
270 }
271
272 /* polling write */
273 ptr = (char *)buffer;
274
275 if (dev->flag & RT_DEVICE_FLAG_STREAM)
276 {
277 /* stream mode */
278 while (size)
279 {
280 if (*ptr == '\n')
281 {
282 while (!(UART_LSR(lpc_serial->hw_base) & 0x20));
283 UART_THR(lpc_serial->hw_base) = '\r';
284 }
285
286 while (!(UART_LSR(lpc_serial->hw_base) & 0x20));
287 UART_THR(lpc_serial->hw_base) = *ptr;
288
289 ptr ++;
290 size --;
291 }
292 }
293 else
294 {
295 while (size)
296 {
297 while (!(UART_LSR(lpc_serial->hw_base) & 0x20));
298 UART_THR(lpc_serial->hw_base) = *ptr;
299
300 ptr ++;
301 size --;
302 }
303 }
304
305 return (rt_size_t) ptr - (rt_size_t) buffer;
306 }
307
rt_hw_serial_init(void)308 void rt_hw_serial_init(void)
309 {
310 struct rt_lpcserial* lpc_serial;
311
312 #ifdef RT_USING_UART1
313 lpc_serial = &serial1;
314
315 lpc_serial->parent.type = RT_Device_Class_Char;
316
317 lpc_serial->hw_base = 0xE000C000;
318 lpc_serial->baudrate = 115200;
319 lpc_serial->irqno = UART0_INT;
320
321 rt_memset(lpc_serial->rx_buffer, 0, sizeof(lpc_serial->rx_buffer));
322 lpc_serial->read_index = lpc_serial->save_index = 0;
323
324 /* Enable UART0 RxD and TxD pins */
325 PINSEL0 |= 0x05;
326
327 /* 8 bits, no Parity, 1 Stop bit */
328 UART_LCR(lpc_serial->hw_base) = 0x83;
329
330 /* Setup Baudrate */
331 UART_DLL(lpc_serial->hw_base) = (PCLK/16/lpc_serial->baudrate) & 0xFF;
332 UART_DLM(lpc_serial->hw_base) = ((PCLK/16/lpc_serial->baudrate) >> 8) & 0xFF;
333
334 /* DLAB = 0 */
335 UART_LCR(lpc_serial->hw_base) = 0x03;
336
337 lpc_serial->parent.type = RT_Device_Class_Char;
338 lpc_serial->parent.init = rt_serial_init;
339 lpc_serial->parent.open = rt_serial_open;
340 lpc_serial->parent.close = rt_serial_close;
341 lpc_serial->parent.read = rt_serial_read;
342 lpc_serial->parent.write = rt_serial_write;
343 lpc_serial->parent.control = rt_serial_control;
344 lpc_serial->parent.user_data = RT_NULL;
345
346 rt_device_register(&lpc_serial->parent,
347 "uart1", RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX);
348 #endif
349
350 #ifdef RT_USING_UART2
351 lpc_serial = &serial2;
352
353 lpc_serial->parent.type = RT_Device_Class_Char;
354
355 lpc_serial->hw_base = 0xE0010000;
356 lpc_serial->baudrate = 115200;
357 lpc_serial->irqno = UART1_INT;
358
359 rt_memset(lpc_serial->rx_buffer, 0, sizeof(lpc_serial->rx_buffer));
360 lpc_serial->read_index = lpc_serial->save_index = 0;
361
362 /* Enable UART1 RxD and TxD pins */
363 PINSEL0 |= 0x05 << 16;
364
365 /* 8 bits, no Parity, 1 Stop bit */
366 UART_LCR(lpc_serial->hw_base) = 0x83;
367
368 /* Setup Baudrate */
369 UART_DLL(lpc_serial->hw_base) = (PCLK/16/lpc_serial->baudrate) & 0xFF;
370 UART_DLM(lpc_serial->hw_base) = ((PCLK/16/lpc_serial->baudrate) >> 8) & 0xFF;
371
372 /* DLAB = 0 */
373 UART_LCR(lpc_serial->hw_base) = 0x03;
374
375 lpc_serial->parent.type = RT_Device_Class_Char;
376 lpc_serial->parent.init = rt_serial_init;
377 lpc_serial->parent.open = rt_serial_open;
378 lpc_serial->parent.close = rt_serial_close;
379 lpc_serial->parent.read = rt_serial_read;
380 lpc_serial->parent.write = rt_serial_write;
381 lpc_serial->parent.control = rt_serial_control;
382 lpc_serial->parent.user_data = RT_NULL;
383
384 rt_device_register(&lpc_serial->parent,
385 "uart2", RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX);
386 #endif
387 }
388
389 /*@}*/
390