264 lines
6.7 KiB
C
264 lines
6.7 KiB
C
/*
|
|
* Copyright (c) 2006-2018, 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)
|
|
{
|
|
/* 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 */
|