rt-thread/bsp/amebaz/drivers/drv_uart.c

269 lines
6.7 KiB
C

/*
* File : drv_uart.c
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2017, RT-Thread Development Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Change Logs:
* Date Author Notes
* 2017-05-30 Bernard the first version
* 2018-03-15 flyingcys add amebaz
*/
#include <rthw.h>
#include <rtthread.h>
#include <rtdevice.h>
#include "board.h"
#include "drv_uart.h"
struct device_uart
{
serial_t serial;
rt_uint32_t irqno;
};
#ifdef BSP_USING_UART0
static struct rt_serial_device serial0;
static struct device_uart uart0;
#endif
static rt_err_t ameba_uart_configure (struct rt_serial_device *serial, struct serial_configure *cfg);
static rt_err_t ameba_uart_control (struct rt_serial_device *serial, int cmd, void *arg);
static int ameba_uart_putc (struct rt_serial_device *serial, char c);
static int ameba_uart_getc (struct rt_serial_device *serial);
static rt_size_t ameba_uart_dma_transmit (struct rt_serial_device *serial, rt_uint8_t *buf, rt_size_t size, int direction);
static void ameba_uart_irq(uint32_t id, SerialIrq event);
const struct rt_uart_ops _uart_ops =
{
ameba_uart_configure,
ameba_uart_control,
ameba_uart_putc,
ameba_uart_getc,
ameba_uart_dma_transmit
};
/*
* UART interface
*/
static rt_err_t ameba_uart_configure (struct rt_serial_device *serial, struct serial_configure *cfg)
{
rt_uint32_t baud_div;
struct device_uart * uart;
RT_ASSERT(serial != RT_NULL);
serial->config = *cfg;
uart = serial->parent.user_data;
RT_ASSERT(uart != RT_NULL);
/* Set databits, stopbits and parity. (8-bit data, 1 stopbit, no parity) */
serial_format(&uart->serial, 8, ParityNone, 1);
/* set baudrate */
serial_baud(&uart->serial, 115200);
return (RT_EOK);
}
static rt_err_t ameba_uart_control (struct rt_serial_device *serial, int cmd, void *arg)
{
struct device_uart * uart;
uart = serial->parent.user_data;
RT_ASSERT(uart != RT_NULL);
switch (cmd)
{
case RT_DEVICE_CTRL_CLR_INT:
/* Disable the UART Interrupt */
serial_irq_set(&uart->serial, RxIrq, 0);
serial_irq_handler(&uart->serial, RT_NULL, 0);
break;
case RT_DEVICE_CTRL_SET_INT:
/* install interrupt */
serial_irq_handler(&uart->serial, ameba_uart_irq, (uint32_t)serial);
/* Enable the UART Interrupt */
serial_irq_set(&uart->serial, RxIrq, 1);
break;
}
return (RT_EOK);
}
static int ameba_uart_putc (struct rt_serial_device *serial, char c)
{
struct device_uart* uart;
uart = serial->parent.user_data;
/* FIFO status, contain valid data */
/* write data */
serial_putc(&uart->serial, c);
return (1);
}
static int ameba_uart_getc (struct rt_serial_device *serial)
{
struct device_uart* uart = serial->parent.user_data;
if(!serial_readable(&uart->serial))
return -1;
/* Receive Data Available */
return serial_getc(&uart->serial);
}
static rt_size_t ameba_uart_dma_transmit (struct rt_serial_device *serial, rt_uint8_t *buf, rt_size_t size, int direction)
{
return (0);
}
static void ameba_uart_irq(uint32_t id, SerialIrq event)
{
struct rt_serial_device *serial = (struct rt_serial_device *)id;
if(event == RxIrq)
{
rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_IND);
}
else if(event == TxIrq)
{
}
}
static rt_err_t dbg_configure(struct rt_serial_device *serial, struct serial_configure *cfg);
static rt_err_t dbg_control(struct rt_serial_device *serial, int cmd, void *arg);
static int dbg_putc(struct rt_serial_device *serial, char c);
static int dbg_getc(struct rt_serial_device *serial);
static struct rt_serial_device ameba_dbg_serial;
const struct rt_uart_ops _ambed_dbg_ops =
{
dbg_configure,
dbg_control,
dbg_putc,
dbg_getc,
RT_NULL,
};
static rt_err_t dbg_configure(struct rt_serial_device *serial, struct serial_configure *cfg)
{
LOGUART_SetBaud(115200);
return RT_EOK;
}
void dbg_uart_irq_handler(void * data)
{
u32 IrqEn = DiagGetIsrEnReg();
DiagSetIsrEnReg(0);
rt_hw_serial_isr(&ameba_dbg_serial, RT_SERIAL_EVENT_RX_IND);
DiagSetIsrEnReg(IrqEn);
}
static rt_err_t dbg_control(struct rt_serial_device *serial, int cmd, void *arg)
{
switch (cmd)
{
case RT_DEVICE_CTRL_CLR_INT:
/* Disable the UART Interrupt */
NVIC_DisableIRQ(UART_LOG_IRQ); /* this is rom_code_patch */
break;
case RT_DEVICE_CTRL_SET_INT:
/* install interrupt */
DIAG_UartReInit((IRQ_FUN) dbg_uart_irq_handler);
/* Enable the UART Interrupt */
NVIC_SetPriority(UART_LOG_IRQ, 10); /* this is rom_code_patch */
break;
}
return (RT_EOK);
}
static int dbg_putc(struct rt_serial_device *serial, char c)
{
DiagPutChar(c);
return 1;
};
static int dbg_getc(struct rt_serial_device *serial)
{
int c = -1;
if(!UART_Readable(UART2_DEV))
return -1;
c = DiagGetChar(_FALSE);
return c;
}
/*
* UART Initiation
*/
int rt_hw_uart_init(void)
{
struct rt_serial_device *serial;
struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;
#ifdef BSP_USING_UART0
{
struct device_uart *uart;
serial = &serial0;
uart = &uart0;
/* Init UART Hardware */
serial_init(&uart->serial, UART_TX, UART_RX);
serial->ops = &_uart_ops;
serial->config = config;
serial->config.baud_rate = 115200;
uart->irqno = UART0_IRQ;
rt_hw_serial_register(serial,
"uart0",
RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX,
uart);
}
#endif
{
serial = &ameba_dbg_serial;
serial->ops = &_ambed_dbg_ops;
serial->config = config;
rt_hw_serial_register(serial,
RT_CONSOLE_DEVICE_NAME,
RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX,
RT_NULL);
}
return 0;
}