/* * Copyright (c) 2006-2022, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes * 2019-02-02 xuzhuoyi first version */ #include "rtdevice.h" #include "board.h" #include "drv_sci.h" #include "F2837xD_device.h" #include "F2837xD_sci.h" typedef long off_t; #include "F2837xD_sci_io.h" #ifdef RT_USING_SERIAL #define LOG_TAG "drv.sci" /* c28x uart driver class */ struct c28x_uart { const char *name; volatile struct SCI_REGS *sci_regs; struct rt_serial_device serial; }; static struct c28x_uart uart_obj[3] = {0}; static rt_err_t c28x_configure(struct rt_serial_device *serial, struct serial_configure *cfg) { struct c28x_uart *uart; RT_ASSERT(serial != RT_NULL); RT_ASSERT(cfg != RT_NULL); uart = (struct c28x_uart *)serial->parent.user_data; RT_ASSERT(uart != RT_NULL); EALLOW; // default config // 1 stop bit, No loopback // No parity,8 char bits, // async mode, idle-line protocol uart->sci_regs->SCICCR.all = 0x0007; // enable TX, RX, internal SCICLK, // Disable RX ERR, SLEEP, TXWAKE uart->sci_regs->SCICTL1.all = 0x0003; uart->sci_regs->SCICTL2.bit.TXINTENA = 1; uart->sci_regs->SCICTL2.bit.RXBKINTENA = 1; uart->sci_regs->SCIHBAUD.all = 0x0000; // 115200 baud @LSPCLK = 22.5MHz (90 MHz SYSCLK). uart->sci_regs->SCILBAUD.all = 53; uart->sci_regs->SCICTL1.all = 0x0023; // Relinquish SCI from Reset switch (cfg->data_bits) { case DATA_BITS_5: uart->sci_regs->SCICCR.bit.SCICHAR = 4; break; case DATA_BITS_6: uart->sci_regs->SCICCR.bit.SCICHAR = 5; break; case DATA_BITS_7: uart->sci_regs->SCICCR.bit.SCICHAR = 6; break; case DATA_BITS_8: uart->sci_regs->SCICCR.bit.SCICHAR = 7; break; default: uart->sci_regs->SCICCR.bit.SCICHAR = 7; break; } switch (cfg->stop_bits) { case STOP_BITS_1: uart->sci_regs->SCICCR.bit.STOPBITS = 0; break; case STOP_BITS_2: uart->sci_regs->SCICCR.bit.STOPBITS = 1; break; default: uart->sci_regs->SCICCR.bit.STOPBITS = 0; break; } switch (cfg->parity) { case PARITY_NONE: uart->sci_regs->SCICCR.bit.PARITYENA = 0; break; case PARITY_ODD: uart->sci_regs->SCICCR.bit.PARITYENA = 1; uart->sci_regs->SCICCR.bit.PARITY = 0; break; case PARITY_EVEN: uart->sci_regs->SCICCR.bit.PARITYENA = 1; uart->sci_regs->SCICCR.bit.PARITY = 1; break; default: uart->sci_regs->SCICCR.bit.PARITYENA = 0; break; } EDIS; return RT_EOK; } static rt_err_t c28x_control(struct rt_serial_device *serial, int cmd, void *arg) { struct c28x_uart *uart; uart = (struct c28x_uart *)serial->parent.user_data; EALLOW; switch (cmd) { /* disable interrupt */ case RT_DEVICE_CTRL_CLR_INT: /* disable interrupt */ uart->sci_regs->SCICTL2.bit.TXINTENA = 0; uart->sci_regs->SCICTL2.bit.RXBKINTENA = 0; break; /* enable interrupt */ case RT_DEVICE_CTRL_SET_INT: /* enable interrupt */ uart->sci_regs->SCICTL2.bit.TXINTENA = 1; uart->sci_regs->SCICTL2.bit.RXBKINTENA = 1; break; } return RT_EOK; } static int c28x_putc(struct rt_serial_device *serial, char c) { SCI_write(0, &c, 1); return 1; } static int c28x_getc(struct rt_serial_device *serial) { char ch; if(SCI_read(0, &ch, 1)) return ch; else return -1; } /** * Uart common interrupt process. This need add to uart ISR. * * @param serial serial device */ static void uart_isr(struct rt_serial_device *serial) { struct c28x_uart *uart = (struct c28x_uart *) serial->parent.user_data; RT_ASSERT(uart != RT_NULL); rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_IND); SciaRegs.SCIFFRX.bit.RXFFINTCLR = 1; // Clear Interrupt flag PieCtrlRegs.PIEACK.all |= 0x100; // Issue PIE ack } static const struct rt_uart_ops c28x_uart_ops = { .configure = c28x_configure, .control = c28x_control, .putc = c28x_putc, .getc = c28x_getc, }; // // sciaRxFifoIsr - SCIA Receive FIFO ISR // interrupt void sciaRxFifoIsr(void) { ALLOW_ISR_PREEMPT(); /* enter interrupt */ rt_interrupt_enter(); uart_isr(&uart_obj[0].serial); /* leave interrupt */ rt_interrupt_leave(); } int rt_hw_sci_init(void) { EALLOW; GpioCtrlRegs.GPBMUX1.bit.GPIO42 = 3; GpioCtrlRegs.GPBMUX1.bit.GPIO43 = 3; GpioCtrlRegs.GPBGMUX1.bit.GPIO42 = 3; GpioCtrlRegs.GPBGMUX1.bit.GPIO43 = 3; GpioCtrlRegs.GPAMUX2.bit.GPIO18 = 2; GpioCtrlRegs.GPAMUX2.bit.GPIO19 = 2; GpioCtrlRegs.GPAGMUX2.bit.GPIO18 = 0; GpioCtrlRegs.GPAGMUX2.bit.GPIO19 = 0; GpioCtrlRegs.GPBMUX2.bit.GPIO56 = 2; GpioCtrlRegs.GPEMUX1.bit.GPIO139 = 2; GpioCtrlRegs.GPBGMUX2.bit.GPIO56 = 1; GpioCtrlRegs.GPEGMUX1.bit.GPIO139 = 1; CpuSysRegs.PCLKCR7.bit.SCI_A = 1; CpuSysRegs.PCLKCR7.bit.SCI_B = 1; CpuSysRegs.PCLKCR7.bit.SCI_C = 1; PieVectTable.SCIA_RX_INT = &sciaRxFifoIsr; EDIS; // // Enable interrupts required for this example // PieCtrlRegs.PIECTRL.bit.ENPIE = 1; // Enable the PIE block PieCtrlRegs.PIEIER9.bit.INTx1 = 1; // PIE Group 9, INT1 IER |= 0x100; // Enable CPU INT struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT; rt_err_t result = 0; uart_obj[0].serial.ops = &c28x_uart_ops; uart_obj[0].serial.config = config; uart_obj[0].name = "scia"; uart_obj[0].sci_regs = &SciaRegs; uart_obj[1].serial.ops = &c28x_uart_ops; uart_obj[1].serial.config = config; uart_obj[1].name = "scib"; uart_obj[1].sci_regs = &ScibRegs; uart_obj[2].serial.ops = &c28x_uart_ops; uart_obj[2].serial.config = config; uart_obj[2].name = "scic"; uart_obj[2].sci_regs = &ScicRegs; /* register UART device */ result = rt_hw_serial_register(&uart_obj[0].serial, uart_obj[0].name, RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX, &uart_obj[0]); /* register UART device */ result = rt_hw_serial_register(&uart_obj[1].serial, uart_obj[1].name, RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX, &uart_obj[1]); /* register UART device */ result = rt_hw_serial_register(&uart_obj[2].serial, uart_obj[2].name, RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX, &uart_obj[2]); return result; } #endif /* RT_USING_SERIAL */