drv_uart.c 3.4 KB
Newer Older
lubi19981001's avatar
lubi19981001 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
/*
 * Copyright (c) 2019-2020, Xim
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 */

#include <rthw.h>
#include <rtdevice.h>

#include "board.h"
#include "drv_uart.h"

#include <stdio.h>
#include "sbi.h"

#define UART_DEFAULT_BAUDRATE               115200

struct device_uart
{
    rt_ubase_t  hw_base;
    rt_uint32_t irqno;
};

static rt_err_t  rt_uart_configure(struct rt_serial_device *serial, struct serial_configure *cfg);
static rt_err_t uart_control(struct rt_serial_device *serial, int cmd, void *arg);
static int       drv_uart_putc(struct rt_serial_device *serial, char c);
static int       drv_uart_getc(struct rt_serial_device *serial);

const struct rt_uart_ops _uart_ops =
{
    rt_uart_configure,
    uart_control,
    drv_uart_putc,
    drv_uart_getc,
    //TODO: add DMA support
    RT_NULL
};

void uart_init(void)
{
    return ;
}

struct rt_serial_device  serial1;
struct device_uart       uart1;

/*
 * UART interface
 */
static rt_err_t rt_uart_configure(struct rt_serial_device *serial, struct serial_configure *cfg)
{
    struct device_uart *uart;

    RT_ASSERT(serial != RT_NULL);
    serial->config = *cfg;

    return (RT_EOK);
}

#define UART_LSR_DR     0x01            /* Data ready */
#define UART_LSR_THRE   0x20            /* Xmit holding register empty */

#define UART_RBR(hw)    HWREG32(hw + 0x00)
#define UART_IER(hw)    HWREG32(hw + 0x04)
#define UART_LSR(hw)    HWREG32(hw + 0x14)

static volatile uint64_t uart_hwbase = 0x10000000;

void uart_putc(char c)
{
    while ((UART_LSR(uart_hwbase) & UART_LSR_THRE) == 0);

    UART_RBR(uart_hwbase) = c;
}

static rt_err_t uart_control(struct rt_serial_device *serial, int cmd, void *arg)
{
    struct device_uart *uart;

    uart = serial->parent.user_data;
    rt_uint32_t channel = 1;

    RT_ASSERT(uart != RT_NULL);
    RT_ASSERT(channel != 3);

    switch (cmd)
    {
    case RT_DEVICE_CTRL_CLR_INT:
        break;

    case RT_DEVICE_CTRL_SET_INT:
        break;
    }

    return (RT_EOK);
}

static int drv_uart_putc(struct rt_serial_device *serial, char c)
{
B
BernardXiong 已提交
101
    sbi_console_putchar(c);
lubi19981001's avatar
lubi19981001 已提交
102 103 104 105 106
    return (1);
}

static int drv_uart_getc(struct rt_serial_device *serial)
{
B
BernardXiong 已提交
107
    return sbi_console_getchar();
lubi19981001's avatar
lubi19981001 已提交
108 109 110 111
}

char rt_hw_console_getchar(void)
{
B
BernardXiong 已提交
112
    return sbi_console_getchar();
lubi19981001's avatar
lubi19981001 已提交
113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165
}

static void uart_rx(void *param)
{
    struct rt_serial_device *serial = (struct rt_serial_device *)param;

    while(1)
    {
        rt_hw_serial_isr((struct rt_serial_device *)serial,RT_SERIAL_EVENT_RX_IND);
        rt_thread_mdelay(10);
    }
}

void rt_hw_uart_start_rx_thread()
{
    rt_thread_t th;
    RT_ASSERT((th = rt_thread_create("uartrx",uart_rx,(void *)&serial1,8192,8,20)) != RT_NULL);
    RT_ASSERT(rt_thread_startup(th) == RT_EOK);
}

/*
 * UART Initiation
 */
int rt_hw_uart_init(void)
{
    struct rt_serial_device *serial;
    struct device_uart      *uart;
    struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;

    {
        serial  = &serial1;
        uart    = &uart1;

        serial->ops              = &_uart_ops;
        serial->config           = config;
        serial->config.baud_rate = UART_DEFAULT_BAUDRATE;

        uart->hw_base   = 0x10000000;
        uart->irqno     = 0xa;

        rt_hw_serial_register(serial,
                              "uart",
                              RT_DEVICE_FLAG_STREAM | RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX,
                              uart);
    }
    
    return 0;
}

/* WEAK for SDK 0.5.6 */
RT_WEAK void uart_debug_init(int uart_channel)
{
}