1 /*
2  * Copyright (c) 2006-2022, RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author       Notes
8  * 2019-02-02     xuzhuoyi     first version
9  */
10 
11 #include "rtdevice.h"
12 #include "board.h"
13 #include "drv_sci.h"
14 #include "F2837xD_device.h"
15 #include "F2837xD_sci.h"
16 
17 //typedef long off_t;
18 #include "F2837xD_sci_io.h"
19 
20 #ifdef RT_USING_SERIAL
21 
22 #define LOG_TAG             "drv.sci"
23 
24 /* c28x uart driver class */
25 struct c28x_uart
26 {
27     const char *name;
28     volatile struct SCI_REGS *sci_regs;
29     struct rt_serial_device serial;
30 };
31 
32 static struct c28x_uart uart_obj[3] = {0};
33 
c28x_configure(struct rt_serial_device * serial,struct serial_configure * cfg)34 static rt_err_t c28x_configure(struct rt_serial_device *serial, struct serial_configure *cfg)
35 {
36     struct c28x_uart *uart;
37     RT_ASSERT(serial != RT_NULL);
38     RT_ASSERT(cfg != RT_NULL);
39     uart = (struct c28x_uart *)serial->parent.user_data;
40     RT_ASSERT(uart != RT_NULL);
41 
42     EALLOW;
43 
44     // default config
45 
46     // 1 stop bit,  No loopback
47     // No parity,8 char bits,
48     // async mode, idle-line protocol
49     uart->sci_regs->SCICCR.all = 0x0007;
50 
51     // enable TX, RX, internal SCICLK,
52     // Disable RX ERR, SLEEP, TXWAKE
53     uart->sci_regs->SCICTL1.all = 0x0003;
54 
55     uart->sci_regs->SCICTL2.bit.TXINTENA = 1;
56     uart->sci_regs->SCICTL2.bit.RXBKINTENA = 1;
57 
58     uart->sci_regs->SCIHBAUD.all = 0x0000;  // 115200 baud @LSPCLK = 22.5MHz (90 MHz SYSCLK).
59     uart->sci_regs->SCILBAUD.all = 53;
60 
61     uart->sci_regs->SCICTL1.all = 0x0023;  // Relinquish SCI from Reset
62 
63     switch (cfg->data_bits)
64     {
65     case DATA_BITS_5:
66         uart->sci_regs->SCICCR.bit.SCICHAR = 4;
67         break;
68     case DATA_BITS_6:
69         uart->sci_regs->SCICCR.bit.SCICHAR = 5;
70         break;
71     case DATA_BITS_7:
72         uart->sci_regs->SCICCR.bit.SCICHAR = 6;
73         break;
74     case DATA_BITS_8:
75         uart->sci_regs->SCICCR.bit.SCICHAR = 7;
76         break;
77     default:
78         uart->sci_regs->SCICCR.bit.SCICHAR = 7;
79         break;
80     }
81     switch (cfg->stop_bits)
82     {
83     case STOP_BITS_1:
84         uart->sci_regs->SCICCR.bit.STOPBITS = 0;
85         break;
86     case STOP_BITS_2:
87         uart->sci_regs->SCICCR.bit.STOPBITS = 1;
88         break;
89     default:
90         uart->sci_regs->SCICCR.bit.STOPBITS = 0;
91         break;
92     }
93     switch (cfg->parity)
94     {
95     case PARITY_NONE:
96         uart->sci_regs->SCICCR.bit.PARITYENA = 0;
97         break;
98     case PARITY_ODD:
99         uart->sci_regs->SCICCR.bit.PARITYENA = 1;
100         uart->sci_regs->SCICCR.bit.PARITY = 0;
101         break;
102     case PARITY_EVEN:
103         uart->sci_regs->SCICCR.bit.PARITYENA = 1;
104         uart->sci_regs->SCICCR.bit.PARITY = 1;
105         break;
106     default:
107         uart->sci_regs->SCICCR.bit.PARITYENA = 0;
108         break;
109     }
110 
111     EDIS;
112 
113     return RT_EOK;
114 }
115 
c28x_control(struct rt_serial_device * serial,int cmd,void * arg)116 static rt_err_t c28x_control(struct rt_serial_device *serial, int cmd, void *arg)
117 {
118     struct c28x_uart *uart;
119     uart = (struct c28x_uart *)serial->parent.user_data;
120 
121     EALLOW;
122 
123     switch (cmd)
124     {
125     /* disable interrupt */
126     case RT_DEVICE_CTRL_CLR_INT:
127         /* disable interrupt */
128         uart->sci_regs->SCICTL2.bit.TXINTENA = 0;
129         uart->sci_regs->SCICTL2.bit.RXBKINTENA = 0;
130         break;
131     /* enable interrupt */
132     case RT_DEVICE_CTRL_SET_INT:
133         /* enable interrupt */
134         uart->sci_regs->SCICTL2.bit.TXINTENA = 1;
135         uart->sci_regs->SCICTL2.bit.RXBKINTENA = 1;
136         break;
137     }
138     return RT_EOK;
139 }
140 
c28x_putc(struct rt_serial_device * serial,char c)141 static int c28x_putc(struct rt_serial_device *serial, char c)
142 {
143     SCI_write(0, &c, 1);
144     return 1;
145 }
146 
c28x_getc(struct rt_serial_device * serial)147 static int c28x_getc(struct rt_serial_device *serial)
148 {
149     char ch;
150     if(SCI_read(0, &ch, 1))
151         return ch;
152     else
153         return -1;
154 }
155 
156 /**
157  * Uart common interrupt process. This need add to uart ISR.
158  *
159  * @param serial serial device
160  */
uart_isr(struct rt_serial_device * serial)161 static void uart_isr(struct rt_serial_device *serial) {
162     struct c28x_uart *uart = (struct c28x_uart *) serial->parent.user_data;
163 
164     RT_ASSERT(uart != RT_NULL);
165 
166     rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_IND);
167     SciaRegs.SCIFFRX.bit.RXFFINTCLR = 1;   // Clear Interrupt flag
168     PieCtrlRegs.PIEACK.all |= 0x100;       // Issue PIE ack
169 }
170 
171 static const struct rt_uart_ops c28x_uart_ops =
172 {
173     .configure = c28x_configure,
174     .control = c28x_control,
175     .putc = c28x_putc,
176     .getc = c28x_getc,
177 };
178 
179 //
180 // sciaRxFifoIsr - SCIA Receive FIFO ISR
181 //
sciaRxFifoIsr(void)182 interrupt void sciaRxFifoIsr(void)
183 {
184     ALLOW_ISR_PREEMPT();
185 
186     /* enter interrupt */
187     rt_interrupt_enter();
188 
189     uart_isr(&uart_obj[0].serial);
190 
191     /* leave interrupt */
192     rt_interrupt_leave();
193 }
194 
rt_hw_sci_init(void)195 int rt_hw_sci_init(void)
196 {
197     EALLOW;
198 
199     GpioCtrlRegs.GPBMUX1.bit.GPIO42 = 3;
200     GpioCtrlRegs.GPBMUX1.bit.GPIO43 = 3;
201     GpioCtrlRegs.GPBGMUX1.bit.GPIO42 = 3;
202     GpioCtrlRegs.GPBGMUX1.bit.GPIO43 = 3;
203 
204     GpioCtrlRegs.GPAMUX2.bit.GPIO18 = 2;
205     GpioCtrlRegs.GPAMUX2.bit.GPIO19 = 2;
206     GpioCtrlRegs.GPAGMUX2.bit.GPIO18 = 0;
207     GpioCtrlRegs.GPAGMUX2.bit.GPIO19 = 0;
208 
209     GpioCtrlRegs.GPBMUX2.bit.GPIO56 = 2;
210     GpioCtrlRegs.GPEMUX1.bit.GPIO139 = 2;
211     GpioCtrlRegs.GPBGMUX2.bit.GPIO56 = 1;
212     GpioCtrlRegs.GPEGMUX1.bit.GPIO139 = 1;
213 
214     CpuSysRegs.PCLKCR7.bit.SCI_A = 1;
215     CpuSysRegs.PCLKCR7.bit.SCI_B = 1;
216     CpuSysRegs.PCLKCR7.bit.SCI_C = 1;
217 
218     PieVectTable.SCIA_RX_INT = &sciaRxFifoIsr;
219 
220     EDIS;
221 
222     //
223     // Enable interrupts required for this example
224     //
225     PieCtrlRegs.PIECTRL.bit.ENPIE = 1;   // Enable the PIE block
226     PieCtrlRegs.PIEIER9.bit.INTx1 = 1;   // PIE Group 9, INT1
227     IER |= 0x100;                        // Enable CPU INT
228 
229     struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;
230     rt_err_t result = 0;
231 
232     uart_obj[0].serial.ops    = &c28x_uart_ops;
233     uart_obj[0].serial.config = config;
234     uart_obj[0].name          = "scia";
235     uart_obj[0].sci_regs      = &SciaRegs;
236 
237     uart_obj[1].serial.ops    = &c28x_uart_ops;
238     uart_obj[1].serial.config = config;
239     uart_obj[1].name          = "scib";
240     uart_obj[1].sci_regs      = &ScibRegs;
241 
242     uart_obj[2].serial.ops    = &c28x_uart_ops;
243     uart_obj[2].serial.config = config;
244     uart_obj[2].name          = "scic";
245     uart_obj[2].sci_regs      = &ScicRegs;
246 
247     /* register UART device */
248     result = rt_hw_serial_register(&uart_obj[0].serial, uart_obj[0].name,
249                                    RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX,
250                                    &uart_obj[0]);
251 
252     /* register UART device */
253     result = rt_hw_serial_register(&uart_obj[1].serial, uart_obj[1].name,
254                                    RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX,
255                                    &uart_obj[1]);
256 
257     /* register UART device */
258     result = rt_hw_serial_register(&uart_obj[2].serial, uart_obj[2].name,
259                                    RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX,
260                                    &uart_obj[2]);
261 
262     return result;
263 }
264 
265 #endif /* RT_USING_SERIAL */
266