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