drv_uart.c 5.7 KB
Newer Older
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
/*
 * File      : drv_uart.c
 * This file is part of RT-Thread RTOS
 * COPYRIGHT (C) 2012, RT-Thread Development Team
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License along
 *  with this program; if not, write to the Free Software Foundation, Inc.,
 *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Change Logs:
 * Date           Author       Notes
 * 2018-02-22     Tanek        first version.
 */

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

#include <SMM_MPS2.h>

#ifdef RT_USING_UART

#ifndef RT_USING_DEVICE
#error "you must define RT_USING_DEVICE with uart device"
34 35
#else
#include <rtdevice.h>
36 37 38
#endif

/* uart driver */
39
struct v2m_uart
40
{
41
    struct rt_serial_device serial;
42 43 44 45 46 47 48 49
    CMSDK_UART_TypeDef * uart_base;

    CMSDK_GPIO_TypeDef * rx_pingpio;   // Pin GPIO
    CMSDK_GPIO_TypeDef * tx_pingpio;
    uint8_t              rx_pinnum;    // Pin Number
    uint8_t              tx_pinnum;

    IRQn_Type            uart_irq_rx;
50
    //IRQn_Type            uart_irq_tx;
51 52 53 54

};

#ifdef RT_USING_UART0
55
struct v2m_uart uart0_device;
56 57 58
#endif

#ifdef RT_USING_UART1
59
struct v2m_uart uart1_device;
60 61 62
#endif

#ifdef RT_USING_UART2
63
struct v2m_uart uart2_device;
64 65
#endif

66
static void uart_irq_handler(struct rt_serial_device *serial)
67 68
{
    uint32_t status;
69
    struct v2m_uart *uart;
70

71
    uart = (struct v2m_uart *)serial->parent.user_data;
72 73 74

    /* enter interrupt */
    rt_interrupt_enter();
75 76 77
    
    status = uart->uart_base->INTSTATUS;
    rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_IND);
78 79 80 81 82 83 84 85 86
    uart->uart_base->INTCLEAR = status;

    /* leave interrupt */
    rt_interrupt_leave();
}

#ifdef RT_USING_UART0
void UART0RX_Handler(void)
{
87
    uart_irq_handler(&uart0_device.serial);
88 89 90 91 92 93
}
#endif

#ifdef RT_USING_UART1
void UART1RX_Handler(void)
{
94
    uart_irq_handler(&uart1_device.serial);
95 96 97 98 99 100
}
#endif

#ifdef RT_USING_UART2
void UART2RX_Handler(void)
{
101
    uart_irq_handler(&uart2_device.serial);
102 103 104
}
#endif

105
static rt_err_t v2m_configure(struct rt_serial_device *serial, struct serial_configure *cfg)
106
{
107
    struct v2m_uart *uart;
108

109 110
    RT_ASSERT(serial != RT_NULL);
    RT_ASSERT(cfg != RT_NULL);
111

112
    uart = (struct v2m_uart *)serial->parent.user_data;
113

114
    uart->uart_base->BAUDDIV = SystemCoreClock / cfg->baud_rate;
115
    uart->uart_base->CTRL = CMSDK_UART_CTRL_TXEN_Msk | CMSDK_UART_CTRL_RXEN_Msk | CMSDK_UART_CTRL_RXIRQEN_Msk;
116 117 118

    uart->rx_pingpio->ALTFUNCSET |= (1u << uart->rx_pinnum);
    uart->tx_pingpio->ALTFUNCSET |= (1u << uart->tx_pinnum);
119 120 121 122

    return RT_EOK;
}

123
static rt_err_t v2m_control(struct rt_serial_device *serial, int cmd, void *arg)
124
{
125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
  struct v2m_uart *uart;

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

  switch (cmd)
  {
  case RT_DEVICE_CTRL_CLR_INT:
      /* disable rx irq */
      NVIC_DisableIRQ(uart->uart_irq_rx);
      break;
  case RT_DEVICE_CTRL_SET_INT:
      /* enable rx irq */
      NVIC_EnableIRQ(uart->uart_irq_rx);
      break;
  }

  return RT_EOK;
143 144
}

145
static int v2m_putc(struct rt_serial_device *serial, char c)
146
{
147 148 149 150 151 152 153 154 155
    struct v2m_uart *uart;

    RT_ASSERT(serial != RT_NULL);
    uart = (struct v2m_uart *)serial->parent.user_data;
    
    while (uart->uart_base->STATE & CMSDK_UART_STATE_TXBF_Msk);
    uart->uart_base->DATA = c;
    
    return 1;
156 157
}

158
static int v2m_getc(struct rt_serial_device *serial)
159
{
160 161
    int ch;
    struct v2m_uart *uart;
162

163 164
    RT_ASSERT(serial != RT_NULL);
    uart = (struct v2m_uart *)serial->parent.user_data;
165

166 167 168 169
    ch = -1;
    if (uart->uart_base->STATE & CMSDK_UART_STATE_RXBF_Msk)
        ch = uart->uart_base->DATA & 0xff;
    return ch;
170 171
}

172
static const struct rt_uart_ops v2m_uart_ops =
173
{
174 175 176 177 178
    v2m_configure,
    v2m_control,
    v2m_putc,
    v2m_getc,
};
179 180 181

int rt_hw_usart_init(void)
{
182
    struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;
183 184
#ifdef RT_USING_UART0
    {
185
        struct v2m_uart* uart;
186 187 188 189 190 191 192

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

        /* device initialization */
        uart->uart_base   = CMSDK_UART0;
        uart->uart_irq_rx = UART0RX_IRQn;
193 194 195 196 197 198 199 200
        
        uart->serial.ops = &v2m_uart_ops;
        uart->serial.config = config;

        rt_hw_serial_register(&uart->serial,
                          "uart0",
                          RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX,
                          uart);
201
    }
202
#endif /* RT_USING_UART0 */
203 204 205

#ifdef RT_USING_UART1
    {
206
        struct v2m_uart* uart;
207 208 209 210 211 212 213

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

        /* device initialization */
        uart->uart_base   = CMSDK_UART1;
        uart->uart_irq_rx = UART1RX_IRQn;
214 215 216 217 218

        rt_hw_serial_register(&uart->serial,
                          "uart1",
                          RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX,
                          uart);
219 220 221 222 223
    }
#endif /* RT_USING_UART1 */

#ifdef RT_USING_UART2
    {
224
        struct v2m_uart* uart;
225 226 227 228 229 230 231

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

        /* device initialization */
        uart->uart_base   = CMSDK_UART2;
        uart->uart_irq_rx = UART2RX_IRQn;
232 233 234 235 236

        rt_hw_serial_register(&uart->serial,
                          "uart2",
                          RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX,
                          uart);
237 238 239 240 241 242 243
    }
#endif /* RT_USING_UART2 */
    return 0;
}
INIT_BOARD_EXPORT(rt_hw_usart_init);

#endif /*RT_USING_UART*/