252 lines
6.2 KiB
C
252 lines
6.2 KiB
C
/*
|
|
* Copyright (c) 2006-2020, RT-Thread Development Team
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*
|
|
* Change Logs:
|
|
* Date Author Notes
|
|
* 2021-02-11 supperthomas first version
|
|
*
|
|
*/
|
|
|
|
|
|
#include "board.h"
|
|
#include "uart.h"
|
|
#include "rtdevice.h"
|
|
#ifdef RT_USING_SERIAL
|
|
|
|
//#define DRV_DEBUG
|
|
//#define LOG_TAG "drv.usart"
|
|
//#include <drv_log.h>
|
|
|
|
#define UART0_CONFIG \
|
|
{ \
|
|
.name = "uart0", \
|
|
.Instance = MXC_UART_GET_UART(0), \
|
|
.irq_type = MXC_UART_GET_IRQ(0), \
|
|
}
|
|
|
|
#define UART1_CONFIG \
|
|
{ \
|
|
.name = "uart1", \
|
|
.Instance = MXC_UART_GET_UART(1), \
|
|
.irq_type = MXC_UART_GET_IRQ(1), \
|
|
}
|
|
|
|
struct mcu_uart_config
|
|
{
|
|
const char *name;
|
|
mxc_uart_regs_t *Instance;
|
|
IRQn_Type irq_type;
|
|
};
|
|
|
|
struct mcu_uart
|
|
{
|
|
mxc_uart_regs_t *handle;
|
|
struct mcu_uart_config *config;
|
|
|
|
rt_uint16_t uart_dma_flag;
|
|
struct rt_serial_device serial;
|
|
};
|
|
|
|
|
|
|
|
|
|
#if !defined(BSP_USING_UART0) && !defined(BSP_USING_UART1)
|
|
|
|
#error "Please define at least one BSP_USING_UARTx"
|
|
/* this driver can be disabled at menuconfig -> RT-Thread Components -> Device Drivers */
|
|
#endif
|
|
|
|
enum
|
|
{
|
|
#ifdef BSP_USING_UART0
|
|
UART0_INDEX,
|
|
#endif
|
|
#ifdef BSP_USING_UART1
|
|
UART1_INDEX,
|
|
#endif
|
|
|
|
};
|
|
|
|
static struct mcu_uart_config uart_config[] =
|
|
{
|
|
#ifdef BSP_USING_UART0
|
|
UART0_CONFIG,
|
|
#endif
|
|
#ifdef BSP_USING_UART1
|
|
UART1_CONFIG,
|
|
#endif
|
|
};
|
|
|
|
static struct mcu_uart uart_obj[sizeof(uart_config) / sizeof(uart_config[0])] = {0};
|
|
|
|
#ifdef BSP_USING_UART1
|
|
void UART1_IRQHandler(void)
|
|
{
|
|
rt_interrupt_enter();
|
|
|
|
rt_hw_serial_isr(&(uart_obj[UART1_INDEX].serial), RT_SERIAL_EVENT_RX_IND);
|
|
|
|
uint32_t intst = 0;
|
|
intst = MXC_UART1->int_fl;
|
|
MXC_UART1->int_fl = intst;
|
|
|
|
rt_interrupt_leave();
|
|
}
|
|
#endif
|
|
|
|
#ifdef BSP_USING_UART0
|
|
void UART0_IRQHandler(void)
|
|
{
|
|
/* enter interrupt */
|
|
rt_interrupt_enter();
|
|
|
|
rt_hw_serial_isr(&(uart_obj[UART0_INDEX].serial), RT_SERIAL_EVENT_RX_IND);
|
|
/* clear flags */
|
|
|
|
uint32_t intst = 0;
|
|
intst = MXC_UART0->int_fl;
|
|
MXC_UART0->int_fl = intst;
|
|
|
|
/* leave interrupt */
|
|
rt_interrupt_leave();
|
|
}
|
|
#endif
|
|
|
|
|
|
static rt_err_t mcu_configure(struct rt_serial_device *serial, struct serial_configure *cfg)
|
|
{
|
|
int error;
|
|
struct mcu_uart *uart;
|
|
RT_ASSERT(serial != RT_NULL);
|
|
RT_ASSERT(cfg != RT_NULL);
|
|
const sys_cfg_uart_t sys_uart_cfg =
|
|
{
|
|
MAP_A,
|
|
UART_FLOW_DISABLE,
|
|
};
|
|
uart = rt_container_of(serial, struct mcu_uart, serial);
|
|
uart_cfg_t mcu_cfg;
|
|
uart->handle = uart->config->Instance;
|
|
mcu_cfg.baud = cfg->baud_rate;
|
|
mcu_cfg.stop = UART_STOP_1;
|
|
mcu_cfg.parity = UART_PARITY_DISABLE;
|
|
mcu_cfg.size = UART_DATA_SIZE_8_BITS;
|
|
mcu_cfg.flow = UART_FLOW_CTRL_EN;
|
|
mcu_cfg.pol = UART_FLOW_POL_EN;
|
|
|
|
error = UART_Init(uart->handle, &mcu_cfg, &sys_uart_cfg);
|
|
if (error != E_NO_ERROR)
|
|
{
|
|
rt_kprintf("Error initializing UART %d\n", error);
|
|
while (1) {}
|
|
}
|
|
return RT_EOK;
|
|
}
|
|
|
|
static rt_err_t mcu_control(struct rt_serial_device *serial, int cmd, void *arg)
|
|
{
|
|
struct mcu_uart *uart;
|
|
|
|
RT_ASSERT(serial != RT_NULL);
|
|
uart = rt_container_of(serial, struct mcu_uart, serial);
|
|
|
|
switch (cmd)
|
|
{
|
|
/* disable interrupt */
|
|
case RT_DEVICE_CTRL_CLR_INT:
|
|
/* disable rx irq */
|
|
NVIC_ClearPendingIRQ(uart->config->irq_type);
|
|
NVIC_DisableIRQ(uart->config->irq_type);
|
|
/* disable interrupt */
|
|
break;
|
|
|
|
/* enable interrupt */
|
|
case RT_DEVICE_CTRL_SET_INT:
|
|
/* enable rx irq */
|
|
NVIC_SetPriority(uart->config->irq_type, 1);
|
|
NVIC_EnableIRQ(uart->config->irq_type);
|
|
/* enable interrupt */
|
|
uart->handle->ctrl |= 0x05 << MXC_F_UART_CTRL_RX_TO_POS;
|
|
uart->handle->int_en |= MXC_F_UART_INT_EN_RX_FIFO_THRESH | \
|
|
MXC_F_UART_INT_EN_RX_TIMEOUT;
|
|
|
|
uart->handle->int_en |= MXC_F_UART_INT_EN_RX_FRAME_ERROR | \
|
|
MXC_F_UART_INT_EN_RX_PARITY_ERROR | \
|
|
MXC_F_UART_INT_EN_RX_OVERRUN ;
|
|
|
|
uart->handle->thresh_ctrl = MXC_UART_FIFO_DEPTH <<
|
|
MXC_F_UART_THRESH_CTRL_RX_FIFO_THRESH_POS;
|
|
break;
|
|
|
|
case RT_DEVICE_CTRL_CLOSE:
|
|
UART_Shutdown(uart->handle);
|
|
break;
|
|
|
|
}
|
|
return RT_EOK;
|
|
}
|
|
|
|
static int mcu_putc(struct rt_serial_device *serial, char c)
|
|
{
|
|
struct mcu_uart *uart;
|
|
RT_ASSERT(serial != RT_NULL);
|
|
|
|
uart = rt_container_of(serial, struct mcu_uart, serial);
|
|
UART_WriteByte(uart->handle, c);
|
|
return 1;
|
|
}
|
|
|
|
static int mcu_getc(struct rt_serial_device *serial)
|
|
{
|
|
int ch;
|
|
struct mcu_uart *uart;
|
|
RT_ASSERT(serial != RT_NULL);
|
|
uart = rt_container_of(serial, struct mcu_uart, serial);
|
|
|
|
ch = -1;
|
|
|
|
if (UART_NumReadAvail(uart->handle))
|
|
{
|
|
ch = UART_ReadByte(uart->handle);
|
|
}
|
|
|
|
return ch;
|
|
}
|
|
|
|
static const struct rt_uart_ops mcu_uart_ops =
|
|
{
|
|
.configure = mcu_configure,
|
|
.control = mcu_control,
|
|
.putc = mcu_putc,
|
|
.getc = mcu_getc,
|
|
};
|
|
|
|
int rt_hw_usart_init(void)
|
|
{
|
|
rt_size_t obj_num = sizeof(uart_obj) / sizeof(struct mcu_uart);
|
|
struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;
|
|
rt_err_t result = 0;
|
|
|
|
for (int i = 0; i < obj_num; i++)
|
|
{
|
|
/* init UART object */
|
|
uart_obj[i].config = &uart_config[i];
|
|
uart_obj[i].serial.ops = &mcu_uart_ops;
|
|
uart_obj[i].serial.config = config;
|
|
|
|
/* register UART device */
|
|
result = rt_hw_serial_register(&uart_obj[i].serial, uart_obj[i].config->name,
|
|
RT_DEVICE_FLAG_RDWR
|
|
| RT_DEVICE_FLAG_INT_RX
|
|
| RT_DEVICE_FLAG_INT_TX
|
|
, RT_NULL);
|
|
RT_ASSERT(result == RT_EOK);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
//INIT_BOARD_EXPORT(rt_hw_usart_init);
|
|
#endif /* RT_USING_SERIAL */
|