drv_uart.c 11.6 KB
Newer Older
B
Bernard Xiong 已提交
1
/*
2
 * Copyright (c) 2006-2021, RT-Thread Development Team
B
Bernard Xiong 已提交
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 */

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

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

#include <stdio.h>
18
#include <sysctl.h>
B
Bernard Xiong 已提交
19

20
#include "uart.h"
B
Bernard Xiong 已提交
21 22 23
#include "uarths.h"
#include "plic.h"

24 25
#define UART_DEFAULT_BAUDRATE               115200

26 27
static volatile uarths_t *const _uarths = (volatile uarths_t *)UARTHS_BASE_ADDR;

B
Bernard Xiong 已提交
28 29 30 31 32 33
struct device_uart
{
    rt_uint32_t hw_base;
    rt_uint32_t irqno;
};

34 35 36 37 38 39 40 41
static rt_err_t  rt_uarths_configure(struct rt_serial_device *serial, struct serial_configure *cfg);
static rt_err_t  uarths_control(struct rt_serial_device *serial, int cmd, void *arg);
static int       drv_uarths_putc(struct rt_serial_device *serial, char c);
static int       drv_uarths_getc(struct rt_serial_device *serial);

static void     uarths_irq_handler(int irqno, void *param);

static rt_err_t  rt_uart_configure(struct rt_serial_device *serial, struct serial_configure *cfg);
B
Bernard Xiong 已提交
42 43 44 45 46 47
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);

static void     uart_irq_handler(int irqno, void *param);

48 49 50 51 52 53 54 55 56
const struct rt_uart_ops _uart_hs_ops =
{
    rt_uarths_configure,
    uarths_control,
    drv_uarths_putc,
    drv_uarths_getc,
    RT_NULL
};

B
Bernard Xiong 已提交
57 58
const struct rt_uart_ops _uart_ops =
{
59
    rt_uart_configure,
B
Bernard Xiong 已提交
60 61 62
    uart_control,
    drv_uart_putc,
    drv_uart_getc,
63
    //TODO: add DMA support
B
Bernard Xiong 已提交
64 65 66
    RT_NULL
};

67 68 69 70 71 72 73 74 75 76
/* START ported from kendryte standalone sdk uart.c */
#define __UART_BRATE_CONST  16

volatile uart_t* const  _uart[3] =
{
    (volatile uart_t*)UART1_BASE_ADDR,
    (volatile uart_t*)UART2_BASE_ADDR,
    (volatile uart_t*)UART3_BASE_ADDR
};

77
void _uart_init(uart_device_number_t channel)
78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
{
    sysctl_clock_enable(SYSCTL_CLOCK_UART1 + channel);
    sysctl_reset(SYSCTL_RESET_UART1 + channel);
}

/* END ported from kendryte standalone sdk uart.c */
static inline uart_device_number_t _get_uart_channel(rt_uint32_t addr)
{
    switch (addr)
    {
        case UART1_BASE_ADDR:
            return UART_DEVICE_1;
        case UART2_BASE_ADDR:
            return UART_DEVICE_2;
        case UART3_BASE_ADDR:
            return UART_DEVICE_3;
        default:
            return UART_DEVICE_MAX;
    }
}

B
Bernard Xiong 已提交
99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115
/*
 * 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;

#ifdef BSP_USING_UART_HS
    {
        static struct rt_serial_device  serial_hs;
        static struct device_uart       uart_hs;

        serial  = &serial_hs;
        uart    = &uart_hs;

116
        serial->ops              = &_uart_hs_ops;
B
Bernard Xiong 已提交
117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
        serial->config           = config;
        serial->config.baud_rate = 115200;

        uart->hw_base   = UARTHS_BASE_ADDR;
        uart->irqno     = IRQN_UARTHS_INTERRUPT;

        rt_hw_serial_register(serial,
                              "uarths",
                              RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX,
                              uart);
    }
#endif

#ifdef BSP_USING_UART1
    {
        static struct rt_serial_device  serial1;
        static struct device_uart       uart1;

        serial  = &serial1;
        uart    = &uart1;

        serial->ops              = &_uart_ops;
        serial->config           = config;
140
        serial->config.baud_rate = UART_DEFAULT_BAUDRATE;
B
Bernard Xiong 已提交
141 142 143 144

        uart->hw_base   = UART1_BASE_ADDR;
        uart->irqno     = IRQN_UART1_INTERRUPT;

145
        _uart_init(UART_DEVICE_1);
146

B
Bernard Xiong 已提交
147
        rt_hw_serial_register(serial,
148
                              "uart1",
B
Bernard Xiong 已提交
149 150 151 152 153 154
                              RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX,
                              uart);
    }
#endif

#ifdef BSP_USING_UART2
155 156 157 158 159 160 161 162 163 164 165 166 167 168
    {
        static struct rt_serial_device  serial2;
        static struct device_uart       uart2;

        serial  = &serial2;
        uart    = &uart2;

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

        uart->hw_base   = UART2_BASE_ADDR;
        uart->irqno     = IRQN_UART2_INTERRUPT;

169
        _uart_init(UART_DEVICE_2);
170 171 172 173 174 175

        rt_hw_serial_register(serial,
                              "uart2",
                              RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX,
                              uart);
    }
B
Bernard Xiong 已提交
176 177 178
#endif

#ifdef BSP_USING_UART3
179 180 181 182 183 184 185 186 187 188 189 190 191 192
    {
        static struct rt_serial_device  serial3;
        static struct device_uart       uart3;

        serial  = &serial3;
        uart    = &uart3;

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

        uart->hw_base   = UART3_BASE_ADDR;
        uart->irqno     = IRQN_UART3_INTERRUPT;

193
        _uart_init(UART_DEVICE_3);
194 195 196 197 198 199

        rt_hw_serial_register(serial,
                              "uart3",
                              RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX,
                              uart);
    }
B
Bernard Xiong 已提交
200 201 202 203 204 205
#endif

    return 0;
}

/*
206
 * UARTHS interface
B
Bernard Xiong 已提交
207
 */
208
static rt_err_t rt_uarths_configure(struct rt_serial_device *serial, struct serial_configure *cfg)
B
Bernard Xiong 已提交
209 210
{
    struct device_uart *uart;
211 212
    uint32_t freq_hs = sysctl_clock_get_freq(SYSCTL_CLOCK_CPU);
    uint16_t div_hs = freq_hs / cfg->baud_rate - 1;
B
Bernard Xiong 已提交
213 214 215 216 217 218 219

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

    uart = serial->parent.user_data;
    RT_ASSERT(uart != RT_NULL);

220 221
    if (uart->hw_base == UARTHS_BASE_ADDR)
    {
222
        _uarths->div.div = div_hs;
223 224 225 226 227 228 229 230 231 232 233
        _uarths->txctrl.txen = 1;
        _uarths->rxctrl.rxen = 1;
        _uarths->txctrl.txcnt = 0;
        _uarths->rxctrl.rxcnt = 0;
        _uarths->ip.txwm = 1;
        _uarths->ip.rxwm = 1;
        _uarths->ie.txwm = 0;
        _uarths->ie.rxwm = 1;
    }
    else
    {
234
        return (-1);
235 236
        /* other uart */
    }
B
Bernard Xiong 已提交
237 238 239 240

    return (RT_EOK);
}

241
static rt_err_t uarths_control(struct rt_serial_device *serial, int cmd, void *arg)
B
Bernard Xiong 已提交
242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257
{
    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 */
        rt_hw_interrupt_mask(uart->irqno);
        break;

    case RT_DEVICE_CTRL_SET_INT:
        /* install interrupt */
258
        rt_hw_interrupt_install(uart->irqno, uarths_irq_handler,
B
Bernard Xiong 已提交
259 260 261 262 263 264 265 266
                                serial, serial->parent.parent.name);
        rt_hw_interrupt_umask(uart->irqno);
        break;
    }

    return (RT_EOK);
}

267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309

static int drv_uarths_putc(struct rt_serial_device *serial, char c)
{
    struct device_uart *uart = serial->parent.user_data;
    RT_ASSERT(uart->hw_base == UARTHS_BASE_ADDR);

    while (_uarths->txdata.full);
    _uarths->txdata.data = (uint8_t)c;

    return (1);
}

static int drv_uarths_getc(struct rt_serial_device *serial)
{
    struct device_uart *uart = serial->parent.user_data;
    RT_ASSERT(uart->hw_base == UARTHS_BASE_ADDR);

    uarths_rxdata_t recv = _uarths->rxdata;
    if (recv.empty)
        return EOF;
    else
        return (recv.data & 0xff);
    /* Receive Data Available */

    return (-1);
}

/* UARTHS ISR */
static void uarths_irq_handler(int irqno, void *param)
{
    struct rt_serial_device *serial = (struct rt_serial_device *)param;
    struct device_uart *uart = serial->parent.user_data;
    RT_ASSERT(uart->hw_base == UARTHS_BASE_ADDR);

    /* read interrupt status and clear it */
    if (_uarths->ip.rxwm)
        rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_IND);
}

/*
 * UART interface
 */
static rt_err_t rt_uart_configure(struct rt_serial_device *serial, struct serial_configure *cfg)
B
Bernard Xiong 已提交
310 311
{
    struct device_uart *uart;
312 313 314 315 316 317 318 319 320 321 322 323
    uart_bitwidth_t data_width = (uart_bitwidth_t)cfg->data_bits ;
    uart_stopbit_t stopbit = (uart_stopbit_t)cfg->stop_bits;
    uart_parity_t parity = (uart_parity_t)cfg->parity;

    uint32_t freq = sysctl_clock_get_freq(SYSCTL_CLOCK_APB0);
    uint32_t divisor = freq / (uint32_t)cfg->baud_rate;
    uint8_t dlh = divisor >> 12;
    uint8_t dll = (divisor - (dlh << 12)) / __UART_BRATE_CONST;
    uint8_t dlf = divisor - (dlh << 12) - dll * __UART_BRATE_CONST;

    RT_ASSERT(serial != RT_NULL);
    serial->config = *cfg;
B
Bernard Xiong 已提交
324 325

    uart = serial->parent.user_data;
326 327 328 329 330 331 332
    RT_ASSERT(uart != RT_NULL);

    uart_device_number_t channel = _get_uart_channel(uart->hw_base);
    RT_ASSERT(channel != UART_DEVICE_MAX);

    RT_ASSERT(data_width >= 5 && data_width <= 8);
    if (data_width == 5)
B
Bernard Xiong 已提交
333
    {
334
        RT_ASSERT(stopbit != UART_STOP_2);
B
Bernard Xiong 已提交
335 336 337
    }
    else
    {
338
        RT_ASSERT(stopbit != UART_STOP_1_5);
B
Bernard Xiong 已提交
339 340
    }

341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374
    uint32_t stopbit_val = stopbit == UART_STOP_1 ? 0 : 1;
    uint32_t parity_val;
    switch (parity)
    {
        case UART_PARITY_NONE:
            parity_val = 0;
            break;
        case UART_PARITY_ODD:
            parity_val = 1;
            break;
        case UART_PARITY_EVEN:
            parity_val = 3;
            break;
        default:
            RT_ASSERT(!"Invalid parity");
            break;
    }

    _uart[channel]->LCR |= 1u << 7;
    _uart[channel]->DLH = dlh;
    _uart[channel]->DLL = dll;
    _uart[channel]->DLF = dlf;
    _uart[channel]->LCR = 0;
    _uart[channel]->LCR = (data_width - 5) |
                          (stopbit_val << 2) |
                          (parity_val << 3);
    _uart[channel]->LCR &= ~(1u << 7);
    _uart[channel]->IER |= 0x80; /* THRE */
    _uart[channel]->FCR = UART_RECEIVE_FIFO_1 << 6 |
                          UART_SEND_FIFO_8 << 4 |
                          0x1 << 3 |
                          0x1;

    return (RT_EOK);
B
Bernard Xiong 已提交
375 376
}

377
static rt_err_t uart_control(struct rt_serial_device *serial, int cmd, void *arg)
B
Bernard Xiong 已提交
378
{
379
    struct device_uart *uart;
B
Bernard Xiong 已提交
380

381 382 383 384 385 386 387
    uart = serial->parent.user_data;
    uart_device_number_t channel = _get_uart_channel(uart->hw_base);

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

    switch (cmd)
B
Bernard Xiong 已提交
388
    {
389 390 391 392 393 394 395 396 397 398 399 400 401
    case RT_DEVICE_CTRL_CLR_INT:
        /* Disable the UART Interrupt */
        rt_hw_interrupt_mask(uart->irqno);
        _uart[channel]->IER &= ~0x1;
        break;

    case RT_DEVICE_CTRL_SET_INT:
        /* install interrupt */
        rt_hw_interrupt_install(uart->irqno, uart_irq_handler,
                                serial, serial->parent.parent.name);
        rt_hw_interrupt_umask(uart->irqno);
        _uart[channel]->IER |= 0x1;
        break;
B
Bernard Xiong 已提交
402 403
    }

404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428
    return (RT_EOK);
}

static int drv_uart_putc(struct rt_serial_device *serial, char c)
{
    struct device_uart *uart = serial->parent.user_data;
    uart_device_number_t channel = _get_uart_channel(uart->hw_base);
    RT_ASSERT(channel != UART_DEVICE_MAX);

    while (_uart[channel]->LSR & (1u << 5));
    _uart[channel]->THR = c;

    return (1);
}

static int drv_uart_getc(struct rt_serial_device *serial)
{
    struct device_uart *uart = serial->parent.user_data;
    uart_device_number_t channel = _get_uart_channel(uart->hw_base);
    RT_ASSERT(channel != UART_DEVICE_MAX);

    if (_uart[channel]->LSR & 1)
        return (char)(_uart[channel]->RBR & 0xff);
    else
        return EOF;
B
Bernard Xiong 已提交
429 430 431 432 433 434 435 436 437 438
    /* Receive Data Available */

    return (-1);
}

/* UART ISR */
static void uart_irq_handler(int irqno, void *param)
{
    struct rt_serial_device *serial = (struct rt_serial_device *)param;
    struct device_uart *uart = serial->parent.user_data;
439 440
    uart_device_number_t channel = _get_uart_channel(uart->hw_base);
    RT_ASSERT(channel != UART_DEVICE_MAX);
B
Bernard Xiong 已提交
441 442

    /* read interrupt status and clear it */
443 444
    if (_uart[channel]->LSR)
        rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_IND);
B
Bernard Xiong 已提交
445
}
446 447 448

/* WEAK for SDK 0.5.6 */

449
RT_WEAK void uart_debug_init(uart_device_number_t uart_channel)
450 451 452
{

}
453