1 /*
2  * Copyright (c) 2006-2020, RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author       Notes
8  * 2021-02-11     supperthomas first version
9  *
10  */
11 
12 
13 #include "board.h"
14 #include "uart.h"
15 #include "rtdevice.h"
16 #ifdef RT_USING_SERIAL
17 
18 //#define DRV_DEBUG
19 //#define LOG_TAG             "drv.usart"
20 //#include <drv_log.h>
21 
22 #define UART0_CONFIG                                                \
23     {                                                               \
24         .name = "uart0",                                            \
25         .Instance = MXC_UART_GET_UART(0),                           \
26         .irq_type = MXC_UART_GET_IRQ(0),                            \
27     }
28 
29 #define UART1_CONFIG                                                \
30     {                                                               \
31         .name = "uart1",                                            \
32         .Instance = MXC_UART_GET_UART(1),                           \
33         .irq_type = MXC_UART_GET_IRQ(1),                            \
34     }
35 
36 struct mcu_uart_config
37 {
38     const char *name;
39     mxc_uart_regs_t *Instance;
40     IRQn_Type irq_type;
41 };
42 
43 struct mcu_uart
44 {
45     mxc_uart_regs_t *handle;
46     struct mcu_uart_config *config;
47 
48     rt_uint16_t uart_dma_flag;
49     struct rt_serial_device serial;
50 };
51 
52 
53 
54 
55 #if !defined(BSP_USING_UART0) && !defined(BSP_USING_UART1)
56 
57 #error "Please define at least one BSP_USING_UARTx"
58 /* this driver can be disabled at menuconfig -> RT-Thread Components -> Device Drivers */
59 #endif
60 
61 enum
62 {
63 #ifdef BSP_USING_UART0
64     UART0_INDEX,
65 #endif
66 #ifdef BSP_USING_UART1
67     UART1_INDEX,
68 #endif
69 
70 };
71 
72 static struct mcu_uart_config uart_config[] =
73 {
74 #ifdef BSP_USING_UART0
75     UART0_CONFIG,
76 #endif
77 #ifdef BSP_USING_UART1
78     UART1_CONFIG,
79 #endif
80 };
81 
82 static struct mcu_uart uart_obj[sizeof(uart_config) / sizeof(uart_config[0])] = {0};
83 
84 #ifdef BSP_USING_UART1
UART1_IRQHandler(void)85 void UART1_IRQHandler(void)
86 {
87     rt_interrupt_enter();
88 
89     rt_hw_serial_isr(&(uart_obj[UART1_INDEX].serial), RT_SERIAL_EVENT_RX_IND);
90 
91     uint32_t  intst = 0;
92     intst = MXC_UART1->int_fl;
93     MXC_UART1->int_fl = intst;
94 
95     rt_interrupt_leave();
96 }
97 #endif
98 
99 #ifdef BSP_USING_UART0
UART0_IRQHandler(void)100 void UART0_IRQHandler(void)
101 {
102     /* enter interrupt */
103     rt_interrupt_enter();
104 
105     rt_hw_serial_isr(&(uart_obj[UART0_INDEX].serial), RT_SERIAL_EVENT_RX_IND);
106     /* clear flags */
107 
108     uint32_t  intst = 0;
109     intst = MXC_UART0->int_fl;
110     MXC_UART0->int_fl = intst;
111 
112     /* leave interrupt */
113     rt_interrupt_leave();
114 }
115 #endif
116 
117 
mcu_configure(struct rt_serial_device * serial,struct serial_configure * cfg)118 static rt_err_t mcu_configure(struct rt_serial_device *serial, struct serial_configure *cfg)
119 {
120     int error;
121     struct mcu_uart *uart;
122     RT_ASSERT(serial != RT_NULL);
123     RT_ASSERT(cfg != RT_NULL);
124     const sys_cfg_uart_t sys_uart_cfg =
125     {
126         MAP_A,
127         UART_FLOW_DISABLE,
128     };
129     uart = rt_container_of(serial, struct mcu_uart, serial);
130     uart_cfg_t mcu_cfg;
131     uart->handle = uart->config->Instance;
132     mcu_cfg.baud = cfg->baud_rate;
133     mcu_cfg.stop = UART_STOP_1;
134     mcu_cfg.parity = UART_PARITY_DISABLE;
135     mcu_cfg.size = UART_DATA_SIZE_8_BITS;
136     mcu_cfg.flow = UART_FLOW_CTRL_EN;
137     mcu_cfg.pol = UART_FLOW_POL_EN;
138 
139     error = UART_Init(uart->handle, &mcu_cfg, &sys_uart_cfg);
140     if (error != E_NO_ERROR)
141     {
142         rt_kprintf("Error initializing UART %d\n", error);
143         while (1) {}
144     }
145     return RT_EOK;
146 }
147 
mcu_control(struct rt_serial_device * serial,int cmd,void * arg)148 static rt_err_t mcu_control(struct rt_serial_device *serial, int cmd, void *arg)
149 {
150     struct mcu_uart *uart;
151 
152     RT_ASSERT(serial != RT_NULL);
153     uart = rt_container_of(serial, struct mcu_uart, serial);
154 
155     switch (cmd)
156     {
157     /* disable interrupt */
158     case RT_DEVICE_CTRL_CLR_INT:
159         /* disable rx irq */
160         NVIC_ClearPendingIRQ(uart->config->irq_type);
161         NVIC_DisableIRQ(uart->config->irq_type);
162         /* disable interrupt */
163         break;
164 
165     /* enable interrupt */
166     case RT_DEVICE_CTRL_SET_INT:
167         /* enable rx irq */
168         NVIC_SetPriority(uart->config->irq_type, 1);
169         NVIC_EnableIRQ(uart->config->irq_type);
170         /* enable interrupt */
171         uart->handle->ctrl |=  0x05 << MXC_F_UART_CTRL_RX_TO_POS;
172         uart->handle->int_en |= MXC_F_UART_INT_EN_RX_FIFO_THRESH | \
173                                 MXC_F_UART_INT_EN_RX_TIMEOUT;
174 
175         uart->handle->int_en |= MXC_F_UART_INT_EN_RX_FRAME_ERROR | \
176                                 MXC_F_UART_INT_EN_RX_PARITY_ERROR | \
177                                 MXC_F_UART_INT_EN_RX_OVERRUN ;
178 
179         uart->handle->thresh_ctrl = MXC_UART_FIFO_DEPTH <<
180                                     MXC_F_UART_THRESH_CTRL_RX_FIFO_THRESH_POS;
181         break;
182 
183     case RT_DEVICE_CTRL_CLOSE:
184         UART_Shutdown(uart->handle);
185         break;
186 
187     }
188     return RT_EOK;
189 }
190 
mcu_putc(struct rt_serial_device * serial,char c)191 static int mcu_putc(struct rt_serial_device *serial, char c)
192 {
193     struct mcu_uart *uart;
194     RT_ASSERT(serial != RT_NULL);
195 
196     uart = rt_container_of(serial, struct mcu_uart, serial);
197     UART_WriteByte(uart->handle, c);
198     return 1;
199 }
200 
mcu_getc(struct rt_serial_device * serial)201 static int mcu_getc(struct rt_serial_device *serial)
202 {
203     int ch;
204     struct mcu_uart *uart;
205     RT_ASSERT(serial != RT_NULL);
206     uart = rt_container_of(serial, struct mcu_uart, serial);
207 
208     ch = -1;
209 
210     if (UART_NumReadAvail(uart->handle))
211     {
212         ch = UART_ReadByte(uart->handle);
213     }
214 
215     return ch;
216 }
217 
218 static const struct rt_uart_ops mcu_uart_ops =
219 {
220     .configure = mcu_configure,
221     .control = mcu_control,
222     .putc = mcu_putc,
223     .getc = mcu_getc,
224 };
225 
rt_hw_usart_init(void)226 int rt_hw_usart_init(void)
227 {
228     rt_size_t obj_num = sizeof(uart_obj) / sizeof(struct mcu_uart);
229     struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;
230     rt_err_t result = 0;
231 
232     for (int i = 0; i < obj_num; i++)
233     {
234         /* init UART object */
235         uart_obj[i].config = &uart_config[i];
236         uart_obj[i].serial.ops    = &mcu_uart_ops;
237         uart_obj[i].serial.config = config;
238 
239         /* register UART device */
240         result = rt_hw_serial_register(&uart_obj[i].serial, uart_obj[i].config->name,
241                                        RT_DEVICE_FLAG_RDWR
242                                        | RT_DEVICE_FLAG_INT_RX
243                                        | RT_DEVICE_FLAG_INT_TX
244                                        , RT_NULL);
245         RT_ASSERT(result == RT_EOK);
246     }
247 
248     return result;
249 }
250 //INIT_BOARD_EXPORT(rt_hw_usart_init);
251 #endif /* RT_USING_SERIAL */
252