drv_uart.c 7.0 KB
Newer Older
B
Bernard Xiong 已提交
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 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
/*
 * File      : drv_uart.c
 * This file is part of RT-Thread RTOS
 * COPYRIGHT (C) 2009-2014 RT-Thread Develop Team
 *
 * The license and distribution terms for this file may be
 * found in the file LICENSE in this distribution or at
 * http://www.rt-thread.org/license/LICENSE
 *
 * Change Logs:
 * Date           Author       Notes
 * 2013-05-18     Bernard      The first version for LPC40xx
 * 2014-12-16     RT_learning  The first version for LPC5410x
 * 2017-08-01     XiaoYang     The first version for LPC546xx
 */


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

#include "fsl_usart.h"
#include "fsl_common.h"
#include "fsl_iocon.h"



struct lpc_uart
{
    USART_Type *UART;
    IRQn_Type UART_IRQn;
};

static rt_err_t lpc_configure(struct rt_serial_device *serial, struct serial_configure *cfg)
{
    struct lpc_uart *uart;
    usart_config_t u0_config;

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

    /*
     * config.baudRate_Bps = 115200U;
     * config.parityMode = kUSART_ParityDisabled;
     * config.stopBitCount = kUSART_OneStopBit;
     * config.loopback = false;
     * config.enableTx = false;
     * config.enableRx = false;
     */
    USART_GetDefaultConfig(&u0_config);
    u0_config.baudRate_Bps = cfg->baud_rate;
    u0_config.enableTx = true;
    u0_config.enableRx = true;

    USART_Init(uart->UART, &u0_config, CLOCK_GetFreq(kCLOCK_Flexcomm0));

    return RT_EOK;
}

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

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

    switch (cmd)
    {
    case RT_DEVICE_CTRL_CLR_INT:
        /* disable rx irq */
        USART_DisableInterrupts(uart->UART, kUSART_RxLevelInterruptEnable);
        break;
    case RT_DEVICE_CTRL_SET_INT:
        /* enable rx irq */
        USART_EnableInterrupts(uart->UART, kUSART_RxLevelInterruptEnable);
        break;
    }

    return RT_EOK;
}

static int lpc_putc(struct rt_serial_device *serial, char c)
{
    struct lpc_uart *uart;

    uart = (struct lpc_uart *)serial->parent.user_data;

    while (!(kUSART_TxFifoNotFullFlag & USART_GetStatusFlags(uart->UART)));

    USART_WriteByte(uart->UART, c);

    return 1;
}

static int lpc_getc(struct rt_serial_device *serial)
{
    struct lpc_uart *uart;

    uart = (struct lpc_uart *)serial->parent.user_data;
    if (kUSART_RxFifoNotEmptyFlag & USART_GetStatusFlags(uart->UART))
    {
        return USART_ReadByte(uart->UART);
    }
    else
        return -1;
}

static const struct rt_uart_ops lpc_uart_ops =
{
    lpc_configure,
    lpc_control,
    lpc_putc,
    lpc_getc,
};


#define IOCON_PIO_DIGITAL_EN        0x0100u   /*!< Enables digital function */
#define IOCON_PIO_FUNC1               0x01u   /*!< Selects pin function 1 */
#define IOCON_PIO_INPFILT_OFF       0x0200u   /*!< Input filter disabled */
#define IOCON_PIO_INV_DI              0x00u   /*!< Input function is not inverted */
#define IOCON_PIO_MODE_INACT          0x00u   /*!< No addition pin function */
#define IOCON_PIO_OPENDRAIN_DI        0x00u   /*!< Open drain is disabled */
#define IOCON_PIO_SLEW_STANDARD       0x00u   /*!< Standard mode, output slew rate control is enabled */
#define PIN29_IDX                       29u   /*!< Pin number for pin 29 in a port 0 */
#define PIN30_IDX                       30u   /*!< Pin number for pin 30 in a port 0 */
#define PORT0_IDX                        0u   /*!< Port index */

/* UART0 device driver structure */
struct lpc_uart uart0 =
{
    USART0,
    FLEXCOMM0_IRQn,
};
struct rt_serial_device serial0;

void FLEXCOMM0_IRQHandler(void)
{
    /* enter interrupt */
    rt_interrupt_enter();

    rt_hw_serial_isr(&serial0, RT_SERIAL_EVENT_RX_IND);

    /* leave interrupt */
    rt_interrupt_leave();
}

void rt_hw_uart_init(void)
{
    struct lpc_uart *uart;
    struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;

D
DengQilong 已提交
152 153
#ifdef RT_USING_UART0
    
B
Bernard Xiong 已提交
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 188 189 190 191 192 193 194
    uart = &uart0;

    serial0.ops    = &lpc_uart_ops;
    serial0.config = config;
    serial0.parent.user_data = uart;

    /* attach 12 MHz clock to FLEXCOMM0 (debug console) */
    CLOCK_AttachClk(kFRO12M_to_FLEXCOMM0);
    /* Enables the clock for the IOCON block. 0 = Disable; 1 = Enable.: 0x01u */
//    CLOCK_EnableClock(kCLOCK_Iocon);
    {
        const uint32_t port0_pin29_config = (
                                                IOCON_PIO_FUNC1 |                                        /* Pin is configured as FC0_RXD_SDA_MOSI */
                                                IOCON_PIO_MODE_INACT |                                   /* No addition pin function */
                                                IOCON_PIO_INV_DI |                                       /* Input function is not inverted */
                                                IOCON_PIO_DIGITAL_EN |                                   /* Enables digital function */
                                                IOCON_PIO_INPFILT_OFF |                                  /* Input filter disabled */
                                                IOCON_PIO_SLEW_STANDARD |                                /* Standard mode, output slew rate control is enabled */
                                                IOCON_PIO_OPENDRAIN_DI                                   /* Open drain is disabled */
                                            );
        IOCON_PinMuxSet(IOCON, PORT0_IDX, PIN29_IDX, port0_pin29_config); /* PORT0 PIN29 (coords: B13) is configured as FC0_RXD_SDA_MOSI */
        const uint32_t port0_pin30_config = (
                                                IOCON_PIO_FUNC1 |                                        /* Pin is configured as FC0_TXD_SCL_MISO */
                                                IOCON_PIO_MODE_INACT |                                   /* No addition pin function */
                                                IOCON_PIO_INV_DI |                                       /* Input function is not inverted */
                                                IOCON_PIO_DIGITAL_EN |                                   /* Enables digital function */
                                                IOCON_PIO_INPFILT_OFF |                                  /* Input filter disabled */
                                                IOCON_PIO_SLEW_STANDARD |                                /* Standard mode, output slew rate control is enabled */
                                                IOCON_PIO_OPENDRAIN_DI                                   /* Open drain is disabled */
                                            );
        IOCON_PinMuxSet(IOCON, PORT0_IDX, PIN30_IDX, port0_pin30_config); /* PORT0 PIN30 (coords: A2) is configured as FC0_TXD_SCL_MISO */
    }

    /* Enable RX interrupt. */
    USART_EnableInterrupts(uart->UART, kUSART_RxLevelInterruptEnable);
    EnableIRQ(uart->UART_IRQn);

    /* register UART0 device */
    rt_hw_serial_register(&serial0, "uart0",
                          RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX | RT_DEVICE_FLAG_STREAM,
                          uart);
D
DengQilong 已提交
195
#endif    
B
Bernard Xiong 已提交
196
}