drv_uart.c 6.2 KB
Newer Older
Thomas_Fly's avatar
Thomas_Fly 已提交
1
/*
Thomas_Fly's avatar
Thomas_Fly 已提交
2
 * Copyright (c) 2006-2020, RT-Thread Development Team
Thomas_Fly's avatar
Thomas_Fly 已提交
3 4 5 6 7
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
Thomas_Fly's avatar
Thomas_Fly 已提交
8 9
 * 2021-02-11     supperthomas first version
 *
Thomas_Fly's avatar
Thomas_Fly 已提交
10 11
 */

Thomas_Fly's avatar
Thomas_Fly 已提交
12

Thomas_Fly's avatar
Thomas_Fly 已提交
13 14 15
#include "board.h"
#include "uart.h"
#include "rtdevice.h"
Thomas_Fly's avatar
Thomas_Fly 已提交
16
#ifdef RT_USING_SERIAL
Thomas_Fly's avatar
Thomas_Fly 已提交
17

Thomas_Fly's avatar
Thomas_Fly 已提交
18 19 20 21
//#define DRV_DEBUG
//#define LOG_TAG             "drv.usart"
//#include <drv_log.h>

Thomas_Fly's avatar
Thomas_Fly 已提交
22 23 24
#define UART0_CONFIG                                                \
    {                                                               \
        .name = "uart0",                                            \
Thomas_Fly's avatar
Thomas_Fly 已提交
25 26
        .Instance = MXC_UART_GET_UART(0),                           \
        .irq_type = MXC_UART_GET_IRQ(0),                            \
Thomas_Fly's avatar
Thomas_Fly 已提交
27 28 29 30 31
    }

#define UART1_CONFIG                                                \
    {                                                               \
        .name = "uart1",                                            \
Thomas_Fly's avatar
Thomas_Fly 已提交
32 33
        .Instance = MXC_UART_GET_UART(1),                           \
        .irq_type = MXC_UART_GET_IRQ(1),                            \
Thomas_Fly's avatar
Thomas_Fly 已提交
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
    }

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;
};


Thomas_Fly's avatar
Thomas_Fly 已提交
53

Thomas_Fly's avatar
Thomas_Fly 已提交
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

#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();
Thomas_Fly's avatar
Thomas_Fly 已提交
88

Thomas_Fly's avatar
Thomas_Fly 已提交
89
    rt_hw_serial_isr(&(uart_obj[UART1_INDEX].serial), RT_SERIAL_EVENT_RX_IND);
Thomas_Fly's avatar
Thomas_Fly 已提交
90

Thomas_Fly's avatar
Thomas_Fly 已提交
91 92 93
    uint32_t  intst = 0;
    intst = MXC_UART1->int_fl;
    MXC_UART1->int_fl = intst;
Thomas_Fly's avatar
Thomas_Fly 已提交
94

Thomas_Fly's avatar
Thomas_Fly 已提交
95 96 97 98 99 100 101 102 103
    rt_interrupt_leave();
}
#endif

#ifdef BSP_USING_UART0
void UART0_IRQHandler(void)
{
    /* enter interrupt */
    rt_interrupt_enter();
Thomas_Fly's avatar
Thomas_Fly 已提交
104

Thomas_Fly's avatar
Thomas_Fly 已提交
105
    rt_hw_serial_isr(&(uart_obj[UART0_INDEX].serial), RT_SERIAL_EVENT_RX_IND);
Thomas_Fly's avatar
Thomas_Fly 已提交
106 107
    /* clear flags */

Thomas_Fly's avatar
Thomas_Fly 已提交
108 109 110
    uint32_t  intst = 0;
    intst = MXC_UART0->int_fl;
    MXC_UART0->int_fl = intst;
Thomas_Fly's avatar
Thomas_Fly 已提交
111

Thomas_Fly's avatar
Thomas_Fly 已提交
112 113 114 115 116 117 118 119
    /* leave interrupt */
    rt_interrupt_leave();
}
#endif


static rt_err_t mcu_configure(struct rt_serial_device *serial, struct serial_configure *cfg)
{
Thomas_Fly's avatar
Thomas_Fly 已提交
120
    int error;
Thomas_Fly's avatar
Thomas_Fly 已提交
121 122 123
    struct mcu_uart *uart;
    RT_ASSERT(serial != RT_NULL);
    RT_ASSERT(cfg != RT_NULL);
Thomas_Fly's avatar
Thomas_Fly 已提交
124 125
    const sys_cfg_uart_t sys_uart_cfg =
    {
Thomas_Fly's avatar
Thomas_Fly 已提交
126 127 128 129 130 131 132 133 134 135 136 137
        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;
Thomas_Fly's avatar
Thomas_Fly 已提交
138 139

    error = UART_Init(uart->handle, &mcu_cfg, &sys_uart_cfg);
Thomas_Fly's avatar
Thomas_Fly 已提交
140 141
    if (error != E_NO_ERROR)
    {
Thomas_Fly's avatar
Thomas_Fly 已提交
142
        rt_kprintf("Error initializing UART %d\n", error);
Thomas_Fly's avatar
Thomas_Fly 已提交
143
        while (1) {}
Thomas_Fly's avatar
Thomas_Fly 已提交
144
    }
Thomas_Fly's avatar
Thomas_Fly 已提交
145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167
    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 */
Thomas_Fly's avatar
Thomas_Fly 已提交
168 169 170 171 172 173
        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;
Thomas_Fly's avatar
Thomas_Fly 已提交
174

Thomas_Fly's avatar
Thomas_Fly 已提交
175 176 177
        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 ;
Thomas_Fly's avatar
Thomas_Fly 已提交
178

Thomas_Fly's avatar
Thomas_Fly 已提交
179 180
        uart->handle->thresh_ctrl = MXC_UART_FIFO_DEPTH <<
                                    MXC_F_UART_THRESH_CTRL_RX_FIFO_THRESH_POS;
Thomas_Fly's avatar
Thomas_Fly 已提交
181 182 183
        break;

    case RT_DEVICE_CTRL_CLOSE:
Thomas_Fly's avatar
Thomas_Fly 已提交
184
        UART_Shutdown(uart->handle);
Thomas_Fly's avatar
Thomas_Fly 已提交
185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209
        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;

Thomas_Fly's avatar
Thomas_Fly 已提交
210
    if (UART_NumReadAvail(uart->handle))
Thomas_Fly's avatar
Thomas_Fly 已提交
211
    {
Thomas_Fly's avatar
Thomas_Fly 已提交
212
        ch = UART_ReadByte(uart->handle);
Thomas_Fly's avatar
Thomas_Fly 已提交
213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243
    }

    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
M
mazhiyuan 已提交
244
                                       , RT_NULL);
Thomas_Fly's avatar
Thomas_Fly 已提交
245 246 247 248 249 250 251
        RT_ASSERT(result == RT_EOK);
    }

    return result;
}
//INIT_BOARD_EXPORT(rt_hw_usart_init);
#endif /* RT_USING_SERIAL */