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 * 2018/10/28 Bernard Unify UART driver for FSL library.
9 * 2019/09/07 niannianyouyu Add the driver of UART1
10 */
11
12 #include <rthw.h>
13 #include <rtthread.h>
14 #include <rtdevice.h>
15
16 #include "board.h"
17 #include "drv_uart.h"
18
19 #include "fsl_lpuart.h"
20
21 struct fsl_uart
22 {
23 LPUART_Type *uart_base;
24 IRQn_Type irqn;
25
26 struct rt_serial_device *serial;
27 char *device_name;
28 };
29
30 static rt_err_t uart_configure(struct rt_serial_device *serial, struct serial_configure *cfg);
31 static rt_err_t uart_control(struct rt_serial_device *serial, int cmd, void *arg);
32 static int uart_putc(struct rt_serial_device *serial, char c);
33 static int uart_getc(struct rt_serial_device *serial);
34 static rt_ssize_t uart_dma_transmit(struct rt_serial_device *serial, rt_uint8_t *buf, rt_size_t size, int direction);
35
36 static void uart_irq_handler(int irqno, void *param);
37
38 const struct rt_uart_ops _uart_ops =
39 {
40 uart_configure,
41 uart_control,
42 uart_putc,
43 uart_getc,
44 uart_dma_transmit
45 };
46
47 static void uart_isr(struct rt_serial_device *serial);
48
49 #if defined(BSP_USING_UART0)
50 struct rt_serial_device serial0;
51
LPUART0_IRQHandler(void)52 void LPUART0_IRQHandler(void)
53 {
54 uart_isr(&serial0);
55 }
56 #endif
57
58 #if defined(BSP_USING_UART1)
59 struct rt_serial_device serial1;
60
LPUART1_IRQHandler(void)61 void LPUART1_IRQHandler(void)
62 {
63 uart_isr(&serial1);
64 }
65 #endif
66
67 static const struct fsl_uart uarts[] =
68 {
69 #ifdef BSP_USING_UART0
70 {
71 LPUART0,
72 LPUART0_IRQn,
73 &serial0,
74 "uart0",
75 },
76 #ifdef BSP_USING_UART1
77 {
78 LPUART1,
79 LPUART1_IRQn,
80 &serial1,
81 "uart1",
82 },
83 #endif
84 #endif
85 };
86
87
88 /*
89 * UART Initiation
90 */
rt_hw_uart_init(void)91 int rt_hw_uart_init(void)
92 {
93 int i;
94 struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;
95
96 for (i = 0; i < sizeof(uarts) / sizeof(uarts[0]); i++)
97 {
98 uarts[i].serial->ops = &_uart_ops;
99 uarts[i].serial->config = config;
100
101 /* register UART device */
102 rt_hw_serial_register(uarts[i].serial,
103 uarts[i].device_name,
104 RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX,
105 (void *)&uarts[i]);
106 }
107
108 return 0;
109 }
110
111 /*
112 * UART interface
113 */
uart_configure(struct rt_serial_device * serial,struct serial_configure * cfg)114 static rt_err_t uart_configure(struct rt_serial_device *serial, struct serial_configure *cfg)
115 {
116 struct fsl_uart *uart;
117 lpuart_config_t config;
118
119 RT_ASSERT(serial != RT_NULL);
120 RT_ASSERT(cfg != RT_NULL);
121
122 uart = (struct fsl_uart *)serial->parent.user_data;
123
124 LPUART_GetDefaultConfig(&config);
125 config.baudRate_Bps = cfg->baud_rate;
126
127 switch (cfg->data_bits)
128 {
129 #if defined(FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT) && FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT
130 case DATA_BITS_7:
131 config.dataBitsCount = kLPUART_SevenDataBits;
132 break;
133 #endif
134
135 default:
136 config.dataBitsCount = kLPUART_EightDataBits;
137 break;
138 }
139
140 switch (cfg->stop_bits)
141 {
142 case STOP_BITS_2:
143 config.stopBitCount = kLPUART_TwoStopBit;
144 break;
145 default:
146 config.stopBitCount = kLPUART_OneStopBit;
147 break;
148 }
149
150 switch (cfg->parity)
151 {
152 case PARITY_ODD:
153 config.parityMode = kLPUART_ParityOdd;
154 break;
155 case PARITY_EVEN:
156 config.parityMode = kLPUART_ParityEven;
157 break;
158 default:
159 config.parityMode = kLPUART_ParityDisabled;
160 break;
161 }
162
163 config.enableTx = true;
164 config.enableRx = true;
165
166 CLOCK_SetIpSrc(kCLOCK_Lpuart0, kCLOCK_IpSrcFircAsync);
167
168 uint32_t uartClkSrcFreq0 = CLOCK_GetIpFreq(kCLOCK_Lpuart0);
169 LPUART_Init(uart->uart_base, &config, uartClkSrcFreq0);
170 LPUART_EnableInterrupts(uart->uart_base, kLPUART_RxDataRegFullInterruptEnable);
171
172 CLOCK_SetIpSrc(kCLOCK_Lpuart1, kCLOCK_IpSrcFircAsync);
173
174 uint32_t uartClkSrcFreq1 = CLOCK_GetIpFreq(kCLOCK_Lpuart1);
175 LPUART_Init(uart->uart_base, &config, uartClkSrcFreq1);
176 LPUART_EnableInterrupts(uart->uart_base, kLPUART_RxDataRegFullInterruptEnable);
177
178 return RT_EOK;
179 }
180
uart_control(struct rt_serial_device * serial,int cmd,void * arg)181 static rt_err_t uart_control(struct rt_serial_device *serial, int cmd, void *arg)
182 {
183 struct fsl_uart *uart;
184
185 RT_ASSERT(serial != RT_NULL);
186 uart = (struct fsl_uart *)serial->parent.user_data;
187
188 switch (cmd)
189 {
190 case RT_DEVICE_CTRL_CLR_INT:
191 /* disable rx irq */
192 DisableIRQ(uart->irqn);
193
194 break;
195 case RT_DEVICE_CTRL_SET_INT:
196 /* enable rx irq */
197 EnableIRQ(uart->irqn);
198 break;
199 }
200
201 return RT_EOK;
202 }
203
uart_putc(struct rt_serial_device * serial,char c)204 static int uart_putc(struct rt_serial_device *serial, char c)
205 {
206 struct fsl_uart *uart;
207
208 RT_ASSERT(serial != RT_NULL);
209 uart = (struct fsl_uart *)serial->parent.user_data;
210
211 LPUART_WriteByte(uart->uart_base, c);
212 while (!(LPUART_GetStatusFlags(uart->uart_base) & kLPUART_TxDataRegEmptyFlag));
213
214 return (1);
215 }
216
uart_getc(struct rt_serial_device * serial)217 static int uart_getc(struct rt_serial_device *serial)
218 {
219 int ch;
220 struct fsl_uart *uart;
221
222 RT_ASSERT(serial != RT_NULL);
223 uart = (struct fsl_uart *)serial->parent.user_data;
224
225 ch = -1;
226 if (LPUART_GetStatusFlags(uart->uart_base) & kLPUART_RxDataRegFullFlag)
227 ch = LPUART_ReadByte(uart->uart_base);
228 return ch;
229 }
230
uart_dma_transmit(struct rt_serial_device * serial,rt_uint8_t * buf,rt_size_t size,int direction)231 static rt_ssize_t uart_dma_transmit(struct rt_serial_device *serial, rt_uint8_t *buf, rt_size_t size, int direction)
232 {
233 return (0);
234 }
235
236 /* UART ISR */
237 /**
238 * Uart common interrupt process. This need add to uart ISR.
239 *
240 * @param serial serial device
241 */
uart_isr(struct rt_serial_device * serial)242 static void uart_isr(struct rt_serial_device *serial)
243 {
244 struct fsl_uart *uart;
245
246 RT_ASSERT(serial != RT_NULL);
247
248 uart = (struct fsl_uart *) serial->parent.user_data;
249 RT_ASSERT(uart != RT_NULL);
250
251 /* UART in mode Receiver */
252 if (LPUART_GetStatusFlags(uart->uart_base) & kLPUART_RxDataRegFullFlag)
253 {
254 rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_IND);
255 }
256
257 /* If RX overrun. */
258 if (LPUART_STAT_OR_MASK & uart->uart_base->STAT)
259 {
260 /* Clear overrun flag, otherwise the RX does not work. */
261 uart->uart_base->STAT = ((uart->uart_base->STAT & 0x3FE00000U) | LPUART_STAT_OR_MASK);
262 }
263 }
264