uart.c 4.8 KB
Newer Older
Y
yangfasheng 已提交
1
/*
2
 * Copyright (c) 2006-2021, RT-Thread Development Team
Y
yangfasheng 已提交
3
 *
4
 * SPDX-License-Identifier: Apache-2.0
Y
yangfasheng 已提交
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 101 102 103 104 105 106 107 108 109 110 111 112 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 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187
 *
 */

#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>

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

#include "board.h"
#include "uart.h"

#include <nrf_gpio.h>

#define UART_RX_BUFSZ 512
rt_uint8_t rx_buffer[UART_RX_BUFSZ];

struct nrf51822_uart
{
    struct rt_device parent;
    struct rt_ringbuffer rx_rb;
} uart_device;

void UART0_IRQHandler(void)
{
    rt_ubase_t level;
    struct nrf51822_uart* uart = &uart_device;

    level = rt_hw_interrupt_disable();

    // Wait for RXD data to be received
    while (NRF_UART0->EVENTS_RXDRDY != 1) ;
    NRF_UART0->EVENTS_RXDRDY = 0;

    rt_hw_interrupt_enable(level);
    /* [Handling the data received over UART] */
    rt_ringbuffer_putchar_force(&(uart->rx_rb), (rt_uint8_t)NRF_UART0->RXD);

    /* invoke callback */
    if(uart->parent.rx_indicate != RT_NULL)
    {
        uart->parent.rx_indicate(&uart->parent, rt_ringbuffer_data_len(&uart->rx_rb));
    }
}


static rt_err_t rt_uart_init (rt_device_t dev)
{
    /* UART Initialization and Enable */
    /** @snippet [Configure UART RX and TX pin] */
    nrf_gpio_cfg_output(TX_PIN_NUMBER);
    nrf_gpio_cfg_input(RX_PIN_NUMBER, NRF_GPIO_PIN_NOPULL);

    NRF_UART0->PSELTXD = TX_PIN_NUMBER;
    NRF_UART0->PSELRXD = RX_PIN_NUMBER;
    /** @snippet [Configure UART RX and TX pin] */
    if (HWFC)
    {
        nrf_gpio_cfg_output(RTS_PIN_NUMBER);
        nrf_gpio_cfg_input(CTS_PIN_NUMBER, NRF_GPIO_PIN_NOPULL);
        NRF_UART0->PSELCTS = CTS_PIN_NUMBER;
        NRF_UART0->PSELRTS = RTS_PIN_NUMBER;
        NRF_UART0->CONFIG  = (UART_CONFIG_HWFC_Enabled << UART_CONFIG_HWFC_Pos);
    }

    NRF_UART0->BAUDRATE      = (UART_BAUDRATE_BAUDRATE_Baud38400 << UART_BAUDRATE_BAUDRATE_Pos);
    NRF_UART0->ENABLE        = (UART_ENABLE_ENABLE_Enabled << UART_ENABLE_ENABLE_Pos);
    NRF_UART0->TASKS_STARTTX = 1;
    NRF_UART0->TASKS_STARTRX = 1;
    NRF_UART0->EVENTS_RXDRDY = 0;

    NRF_UART0->INTENSET = (UART_INTENSET_RXDRDY_Enabled << UART_INTENSET_RXDRDY_Pos);

    NVIC_EnableIRQ(UART0_IRQn);

    return RT_EOK;
}

static rt_err_t rt_uart_open(rt_device_t dev, rt_uint16_t oflag)
{
    RT_ASSERT(dev != RT_NULL);
    if (dev->flag & RT_DEVICE_FLAG_INT_RX)
    {
        /* Enable the UART Interrupt */
        NVIC_EnableIRQ(UART0_IRQn);
    }

    return RT_EOK;
}

static rt_err_t rt_uart_close(rt_device_t dev)
{
    RT_ASSERT(dev != RT_NULL);
    if (dev->flag & RT_DEVICE_FLAG_INT_RX)
    {
        /* Disable the UART Interrupt */
        NVIC_DisableIRQ(UART0_IRQn);
    }

    return RT_EOK;
}

static rt_size_t rt_uart_read(rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size)
{
    rt_size_t length;
    struct nrf51822_uart *uart = (struct nrf51822_uart*)dev;
    /* interrupt receive */
    rt_base_t level;

    RT_ASSERT(uart != RT_NULL);

    /* disable interrupt */
    level = rt_hw_interrupt_disable();
    length = rt_ringbuffer_get(&(uart->rx_rb), buffer, size);
    /* enable interrupt */
    rt_hw_interrupt_enable(level);

    return length;
}

static rt_size_t rt_uart_write(rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size)
{
    char *ptr;
    ptr = (char*) buffer;

    if (dev->open_flag & RT_DEVICE_FLAG_STREAM)
    {
        /* stream mode */
        while (size)
        {
            if (*ptr == '\n')
            {
                NRF_UART0->TXD = (uint8_t)'\r';

                // Wait for TXD data to be sent.
                while (NRF_UART0->EVENTS_TXDRDY != 1) ;

                NRF_UART0->EVENTS_TXDRDY = 0;
            }

            NRF_UART0->TXD = (uint8_t)(*ptr);

            // Wait for TXD data to be sent.
            while (NRF_UART0->EVENTS_TXDRDY != 1) ;

            NRF_UART0->EVENTS_TXDRDY = 0;

            ptr ++;
            size --;
        }
    }
    else
    {
        while ( size != 0 )
        {
            NRF_UART0->TXD = (uint8_t)(*ptr);

            // Wait for TXD data to be sent.
            while (NRF_UART0->EVENTS_TXDRDY != 1) ;

            NRF_UART0->EVENTS_TXDRDY = 0;

            ptr++;
            size--;
        }
    }

    return (rt_size_t) ptr - (rt_size_t) buffer;
}

void rt_hw_uart_init(void)
{
    struct nrf51822_uart* uart;

    /* get uart device */
    uart = &uart_device;

    /* device initialization */
    uart->parent.type = RT_Device_Class_Char;
    rt_ringbuffer_init(&(uart->rx_rb), rx_buffer, sizeof(rx_buffer));

    /* device interface */
mysterywolf's avatar
mysterywolf 已提交
188 189
    uart->parent.init       = rt_uart_init;
    uart->parent.open       = rt_uart_open;
Y
yangfasheng 已提交
190
    uart->parent.close      = rt_uart_close;
mysterywolf's avatar
mysterywolf 已提交
191
    uart->parent.read       = rt_uart_read;
Y
yangfasheng 已提交
192 193 194 195 196 197
    uart->parent.write      = rt_uart_write;
    uart->parent.control    = RT_NULL;
    uart->parent.user_data  = RT_NULL;

    rt_device_register(&uart->parent, "uart0", RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX);
}