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