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  * 2020-08-06     whik         first version
9  */
10 #include <rthw.h>
11 #include <rtthread.h>
12 #include <rtdevice.h>
13 
14 #include "drv_uart.h"
15 
16 struct sf2_uart
17 {
18     mss_uart_instance_t *uart;
19     IRQn_Type irq;
20 };
21 
22 struct sf2_uart uart0=
23 {
24     &g_mss_uart0,
25     UART0_IRQn,
26 };
27 struct rt_serial_device serial0;
28 
uart0_rx_handler(mss_uart_instance_t * this_uart)29 void uart0_rx_handler(mss_uart_instance_t *this_uart)
30 {
31     /* enter interrupt */
32     rt_interrupt_enter();
33     rt_hw_serial_isr(&serial0, RT_SERIAL_EVENT_RX_IND);
34     /* leave interrupt */
35     rt_interrupt_leave();
36 }
37 
38 struct sf2_uart uart1=
39 {
40     &g_mss_uart1,
41     UART1_IRQn,
42 };
43 
44 struct rt_serial_device serial1;
uart1_rx_handler(mss_uart_instance_t * this_uart)45 void uart1_rx_handler(mss_uart_instance_t *this_uart)
46 {
47     /* enter interrupt */
48     rt_interrupt_enter();
49     rt_hw_serial_isr(&serial1, RT_SERIAL_EVENT_RX_IND);
50     /* leave interrupt */
51     rt_interrupt_leave();
52 }
53 
sf2_uart_configure(struct rt_serial_device * serial,struct serial_configure * cfg)54 static rt_err_t sf2_uart_configure(struct rt_serial_device *serial,
55                                    struct serial_configure *cfg)
56 {
57     uint32_t baudRate;
58     uint8_t datBits, parity, stopBits;
59     uint8_t config;
60     struct sf2_uart *uart;
61 
62     RT_ASSERT(serial != RT_NULL);
63     RT_ASSERT(cfg != RT_NULL);
64 
65     uart = (struct sf2_uart *)serial->parent.user_data;
66 
67     switch(cfg->data_bits)
68     {
69         case DATA_BITS_5: datBits = MSS_UART_DATA_5_BITS; break;
70         case DATA_BITS_6: datBits = MSS_UART_DATA_6_BITS; break;
71         case DATA_BITS_7: datBits = MSS_UART_DATA_7_BITS; break;
72         case DATA_BITS_8: datBits = MSS_UART_DATA_8_BITS; break;
73         default:          datBits = MSS_UART_DATA_8_BITS; break;
74     }
75     switch(cfg->parity)
76     {
77         case PARITY_NONE: parity = MSS_UART_NO_PARITY;   break;
78         case PARITY_EVEN: parity = MSS_UART_EVEN_PARITY; break;
79         case PARITY_ODD : parity = MSS_UART_ODD_PARITY;  break;
80         default         : parity = MSS_UART_NO_PARITY;   break;
81     }
82     switch(cfg->stop_bits)
83     {
84         case STOP_BITS_1: stopBits = MSS_UART_ONE_STOP_BIT; break;
85         case STOP_BITS_2: stopBits = MSS_UART_TWO_STOP_BITS; break;
86         case STOP_BITS_3: stopBits = MSS_UART_ONEHALF_STOP_BIT; break;
87         default         : stopBits = MSS_UART_ONE_STOP_BIT;
88     }
89 
90     baudRate = cfg->baud_rate;
91     config = datBits | parity | stopBits;
92 
93     MSS_UART_init(uart->uart, baudRate, config);
94     if(uart->uart == &g_mss_uart0)
95         MSS_UART_set_rx_handler(uart->uart, uart0_rx_handler, MSS_UART_FIFO_SINGLE_BYTE);
96     else
97         MSS_UART_set_rx_handler(uart->uart, uart1_rx_handler, MSS_UART_FIFO_SINGLE_BYTE);
98 
99     return RT_EOK;
100 }
101 
sf2_uart_control(struct rt_serial_device * serial,int cmd,void * arg)102 static rt_err_t sf2_uart_control(struct rt_serial_device *serial,
103                                   int cmd, void *arg)
104 {
105     struct sf2_uart* uart;
106 
107     RT_ASSERT(serial != RT_NULL);
108     uart = (struct sf2_uart*)serial->parent.user_data;
109 
110     switch (cmd)
111     {
112         case RT_DEVICE_CTRL_CLR_INT:
113             NVIC_DisableIRQ(uart->irq);
114             break;
115         case RT_DEVICE_CTRL_SET_INT:
116             NVIC_EnableIRQ(uart->irq);
117             break;
118     }
119 
120     return RT_EOK;
121 }
122 
sf2_uart_putc(struct rt_serial_device * serial,char c)123 static int sf2_uart_putc(struct rt_serial_device *serial, char c)
124 {
125     struct sf2_uart* uart;
126     uint32_t tx_ready;
127 
128     RT_ASSERT(serial != RT_NULL);
129 
130     uart = (struct sf2_uart*)serial->parent.user_data;
131 
132     do {
133         tx_ready = uart->uart->hw_reg->LSR & 0x20u;
134     } while(!tx_ready);
135     uart->uart->hw_reg->THR = c;
136 
137     return 1;
138 }
139 
sf2_uart_getc(struct rt_serial_device * serial)140 static int sf2_uart_getc(struct rt_serial_device *serial)
141 {
142     int ch = -1;
143     uint8_t err_status;
144     struct sf2_uart* uart;
145 
146     RT_ASSERT(serial != RT_NULL);
147     uart = (struct sf2_uart*)serial->parent.user_data;
148 
149     err_status = MSS_UART_get_rx_status(uart->uart);
150     if(MSS_UART_NO_ERROR == err_status)
151         MSS_UART_get_rx(uart->uart, (uint8_t *)&ch, 1);
152 
153     return ch;
154 }
155 
156 static const struct rt_uart_ops sf2_uart_ops =
157 {
158     sf2_uart_configure,
159     sf2_uart_control,
160     sf2_uart_putc,
161     sf2_uart_getc,
162 };
163 
rt_hw_uart_init(void)164 int rt_hw_uart_init(void)
165 {
166     rt_err_t result = RT_EOK;
167     struct sf2_uart* uart;
168     struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;
169 
170 #ifdef BSP_USING_UART0
171     uart = &uart0;
172     serial0.ops = &sf2_uart_ops;
173     /* default config: 115200, 8, no, 1 */
174     serial0.config = config;
175     result = rt_hw_serial_register(&serial0, "uart0", RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX, uart);
176     RT_ASSERT(result == RT_EOK);
177 #endif
178 
179 #ifdef BSP_USING_UART1
180     uart = &uart1;
181     serial1.ops = &sf2_uart_ops;
182     /* default config: 115200, 8, no, 1 */
183     serial1.config = config;
184     result = rt_hw_serial_register(&serial1, "uart1", RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX, uart);
185     RT_ASSERT(result == RT_EOK);
186 #endif
187     return result;
188 }
189 INIT_BOARD_EXPORT(rt_hw_uart_init);
190