• RT-Thread 4.0.3 适配 UART_V2 版本


    RT-Thread 4.0.3 适配 UART_V2 版本

    本文为针对发布版4.0.3 进行 UART_V2 驱动的移植适配操作笔记。

    由于使用了 libmodbus 软件包,需要 posix_termios 支持,但新版 serial_v2.c 还未支持,下面移植时添加对应适配代码。

    [串口 V2 适配指南](RT-Thread-串口 V2 适配指南RT-Thread问答社区 - RT-Thread)主要是基于主干开发版的移植,下面以实际项目(基于STM32F407)使用发布版4.0.3 的BSP开发为例进行移植说明.

    详情参考

    [UART 设备 v2 版本]

    [串口 V2 适配指南](RT-Thread-串口 V2 适配指南RT-Thread问答社区 - RT-Thread)

    V2驱动文件添加

    从主干版本获取新版驱动文件:

    drv_usart_v2.c drv_usart_v2.h 放入 bsp的 libraries/HAL_Drivers/ 目录下

    serial_v2.c 放入 components/drivers/serial/serial_v2.c

    serial_v2.h 放入 components/drivers/include/drivers/serial_v2.h

    修改驱动层支持 UART_V2

    1. libraries/HAL_Drivers/SConscript

    if GetDepend(['RT_USING_SERIAL']):
        if GetDepend(['RT_USING_SERIAL_V2']):
            src += ['drv_usart_v2.c']
        else:
            src += ['drv_usart.c']
    

    2. libraries/HAL_Drivers/drv_common.c

    #ifdef RT_USING_SERIAL
    #ifdef RT_USING_SERIAL_V2
    #include "drv_usart_v2.h"
    #else
    #include "drv_usart.h"
    #endif
    #endif
    

    3. libraries/HAL_Drivers/drv_usart_v2.c

    stm32_uart_get_config 增加 UART5~8的支持

    #ifdef BSP_USING_UART5
        uart_obj[UART5_INDEX].serial.config = config;
        uart_obj[UART5_INDEX].uart_dma_flag = 0;
    
        uart_obj[UART5_INDEX].serial.config.rx_bufsz = BSP_UART5_RX_BUFSIZE;
        uart_obj[UART5_INDEX].serial.config.tx_bufsz = BSP_UART5_TX_BUFSIZE;
    
    #ifdef BSP_UART5_RX_USING_DMA
        uart_obj[UART5_INDEX].uart_dma_flag |= RT_DEVICE_FLAG_DMA_RX;
        static struct dma_config uart5_dma_rx = UART5_DMA_RX_CONFIG;
        uart_config[UART5_INDEX].dma_rx = &uart5_dma_rx;
    #endif
    
    #ifdef BSP_UART5_TX_USING_DMA
        uart_obj[UART5_INDEX].uart_dma_flag |= RT_DEVICE_FLAG_DMA_TX;
        static struct dma_config uart5_dma_tx = UART5_DMA_TX_CONFIG;
        uart_config[UART5_INDEX].dma_tx = &uart5_dma_tx;
    #endif
    #endif
    
    #ifdef BSP_USING_UART6
        uart_obj[UART6_INDEX].serial.config = config;
        uart_obj[UART6_INDEX].uart_dma_flag = 0;
    
        uart_obj[UART6_INDEX].serial.config.rx_bufsz = BSP_UART6_RX_BUFSIZE;
        uart_obj[UART6_INDEX].serial.config.tx_bufsz = BSP_UART6_TX_BUFSIZE;
    
    #ifdef BSP_UART6_RX_USING_DMA
        uart_obj[UART6_INDEX].uart_dma_flag |= RT_DEVICE_FLAG_DMA_RX;
        static struct dma_config uart6_dma_rx = UART6_DMA_RX_CONFIG;
        uart_config[UART6_INDEX].dma_rx = &uart6_dma_rx;
    #endif
    
    #ifdef BSP_UART6_TX_USING_DMA
        uart_obj[UART6_INDEX].uart_dma_flag |= RT_DEVICE_FLAG_DMA_TX;
        static struct dma_config uart6_dma_tx = UART6_DMA_TX_CONFIG;
        uart_config[UART6_INDEX].dma_tx = &uart6_dma_tx;
    #endif
    #endif
    
    #ifdef BSP_USING_UART7
        uart_obj[UART7_INDEX].serial.config = config;
        uart_obj[UART7_INDEX].uart_dma_flag = 0;
    
        uart_obj[UART7_INDEX].serial.config.rx_bufsz = BSP_UART7_RX_BUFSIZE;
        uart_obj[UART7_INDEX].serial.config.tx_bufsz = BSP_UART7_TX_BUFSIZE;
    
    #ifdef BSP_UART7_RX_USING_DMA
        uart_obj[UART7_INDEX].uart_dma_flag |= RT_DEVICE_FLAG_DMA_RX;
        static struct dma_config uart7_dma_rx = UART7_DMA_RX_CONFIG;
        uart_config[UART7_INDEX].dma_rx = &uart7_dma_rx;
    #endif
    
    #ifdef BSP_UART7_TX_USING_DMA
        uart_obj[UART7_INDEX].uart_dma_flag |= RT_DEVICE_FLAG_DMA_TX;
        static struct dma_config uart7_dma_tx = UART7_DMA_TX_CONFIG;
        uart_config[UART7_INDEX].dma_tx = &uart7_dma_tx;
    #endif
    #endif
    
    #ifdef BSP_USING_UART8
        uart_obj[UART8_INDEX].serial.config = config;
        uart_obj[UART8_INDEX].uart_dma_flag = 0;
    
        uart_obj[UART8_INDEX].serial.config.rx_bufsz = BSP_UART8_RX_BUFSIZE;
        uart_obj[UART8_INDEX].serial.config.tx_bufsz = BSP_UART8_TX_BUFSIZE;
    
    #ifdef BSP_UART8_RX_USING_DMA
        uart_obj[UART8_INDEX].uart_dma_flag |= RT_DEVICE_FLAG_DMA_RX;
        static struct dma_config uart8_dma_rx = UART8_DMA_RX_CONFIG;
        uart_config[UART8_INDEX].dma_rx = &uart8_dma_rx;
    #endif
    
    #ifdef BSP_UART8_TX_USING_DMA
        uart_obj[UART8_INDEX].uart_dma_flag |= RT_DEVICE_FLAG_DMA_TX;
        static struct dma_config uart8_dma_tx = UART8_DMA_TX_CONFIG;
        uart_config[UART8_INDEX].dma_tx = &uart8_dma_tx;
    #endif
    #endif
    

    4. components/drivers/Kconfig

    menuconfig RT_USING_SERIAL
        bool "Using serial device drivers"
        select RT_USING_DEVICE_IPC
        select RT_USING_DEVICE
        default y
    
        if RT_USING_SERIAL
            choice
                prompt "Choice Serial version"
                default RT_USING_SERIAL_V1
                config RT_USING_SERIAL_V1
                    bool "RT_USING_SERIAL_V1"
                config RT_USING_SERIAL_V2
                    bool "RT_USING_SERIAL_V2"
            endchoice
            config RT_SERIAL_USING_DMA
                bool "Enable serial DMA mode"
                default y
    
            config RT_SERIAL_RB_BUFSZ
                int "Set RX buffer size"
                depends on !RT_USING_SERIAL_V2
                default 64
        endif
    

    5. components/drivers/serial/SConscript

    from building import *
    
    cwd = GetCurrentDir()
    CPPPATH = [cwd + '/../include']
    group = []
    if GetDepend(['RT_USING_SERIAL']):
        if GetDepend(['RT_USING_SERIAL_V2']):
            src = Glob('serial_v2.c')
            group = DefineGroup('DeviceDrivers', src, depend = ['RT_USING_SERIAL_V2'], CPPPATH = CPPPATH)
        else:
            src = Glob('serial.c')
            group = DefineGroup('DeviceDrivers', src, depend = ['RT_USING_SERIAL'], CPPPATH = CPPPATH)
    
    Return('group')
    

    6. components/drivers/include/rtdevice.h

    #ifdef RT_USING_SERIAL
    #ifdef RT_USING_SERIAL_V2
    #include "drivers/serial_v2.h"
    #else
    #include "drivers/serial.h"
    #endif
    #endif /* RT_USING_SERIAL */
    

    修改应用层 Kconfig

    board/Kconfig

    menuconfig BSP_USING_UART
            bool "Enable UART"
            default y
            select RT_USING_SERIAL
            select RT_SERIAL_USING_DMA
            if BSP_USING_UART
                menuconfig BSP_USING_UART1
                    bool "Enable UART1"
                    default y
                    if BSP_USING_UART1
                        config BSP_UART1_RX_USING_DMA
                            bool "Enable UART1 RX DMA"
                            depends on BSP_USING_UART1 && RT_SERIAL_USING_DMA
                            default n
    
                        config BSP_UART1_TX_USING_DMA
                            bool "Enable UART1 TX DMA"
                            depends on BSP_USING_UART1 && RT_SERIAL_USING_DMA
                            default n
    
                        config BSP_UART1_RX_BUFSIZE
                            int "Set UART1 RX buffer size"
                            range 64 65535
                            depends on RT_USING_SERIAL_V2
                            default 256
    
                        config BSP_UART1_TX_BUFSIZE
                            int "Set UART1 TX buffer size"
                            range 0 65535
                            depends on RT_USING_SERIAL_V2
                            default 0
                    endif
    
                menuconfig BSP_USING_UART2
                    bool "Enable UART2"
                    default y
                    if BSP_USING_UART2
                        config BSP_UART2_RX_USING_DMA
                            bool "Enable UART2 RX DMA"
                            depends on BSP_USING_UART2 && RT_SERIAL_USING_DMA
                            default n
    
                        config BSP_UART2_TX_USING_DMA
                            bool "Enable UART2 TX DMA"
                            depends on BSP_USING_UART2 && RT_SERIAL_USING_DMA
                            default n
    
                        config BSP_UART2_RX_BUFSIZE
                            int "Set UART2 RX buffer size"
                            range 64 65535
                            depends on RT_USING_SERIAL_V2
                            default 256
    
                        config BSP_UART2_TX_BUFSIZE
                            int "Set UART2 TX buffer size"
                            range 0 65535
                            depends on RT_USING_SERIAL_V2
                            default 0
                    endif
    

    其余使用串口参考着添加

    修改相关文件适配 posix_termios

    修改 components/drivers/serial/serial_v2.c 以支持 posix_termios

    #ifdef RT_USING_POSIX_TERMIOS
    #include <posix_termios.h>
    #endif
    

    #ifdef RT_USING_POSIX_TERMIOS
    struct speed_baudrate_item
    {
        speed_t speed;
        int baudrate;
    };
    
    const static struct speed_baudrate_item _tbl[] =
    {
        {B2400, BAUD_RATE_2400},
        {B4800, BAUD_RATE_4800},
        {B9600, BAUD_RATE_9600},
        {B19200, BAUD_RATE_19200},
        {B38400, BAUD_RATE_38400},
        {B57600, BAUD_RATE_57600},
        {B115200, BAUD_RATE_115200},
        {B230400, BAUD_RATE_230400},
        {B460800, BAUD_RATE_460800},
        {B921600, BAUD_RATE_921600},
        {B2000000, BAUD_RATE_2000000},
        {B3000000, BAUD_RATE_3000000},
    };
    
    static speed_t _get_speed(int baudrate)
    {
        int index;
    
        for (index = 0; index < sizeof(_tbl)/sizeof(_tbl[0]); index ++)
        {
            if (_tbl[index].baudrate == baudrate)
                return _tbl[index].speed;
        }
    
        return B0;
    }
    
    static int _get_baudrate(speed_t speed)
    {
        int index;
    
        for (index = 0; index < sizeof(_tbl)/sizeof(_tbl[0]); index ++)
        {
            if (_tbl[index].speed == speed)
                return _tbl[index].baudrate;
        }
    
        return 0;
    }
    
    static void _tc_flush(struct rt_serial_device *serial, int queue)
    {
        rt_base_t level;
        int ch = -1;
        struct rt_serial_rx_fifo *rx_fifo = RT_NULL;    /* 接收环形缓冲 */
    
        RT_ASSERT(serial != RT_NULL);
    
        rx_fifo = (struct rt_serial_rx_fifo *) serial->serial_rx;
    
        switch(queue)
        {
            case TCIFLUSH:
            case TCIOFLUSH:
    
                RT_ASSERT(rx_fifo != RT_NULL);
    
                if (serial->config.rx_bufsz > 0)
                {
                    RT_ASSERT(RT_NULL != rx_fifo);
                    level = rt_hw_interrupt_disable();
                    rx_fifo->rb.read_index = rx_fifo->rb.write_index;
                    rt_hw_interrupt_enable(level);
                }
                else
                {
                    while (1)
                    {
                        ch = serial->ops->getc(serial);
                        if (ch == -1) break;
                    }
                }
    
                break;
    
             case TCOFLUSH:
                break;
        }
    
    }
    #endif  /* RT_USING_POSIX_TERMIOS */
    

    static rt_err_t rt_serial_control(struct rt_device *dev,
                                      int               cmd,
                                      void             *args)
    {
        rt_err_t ret = RT_EOK;
        struct rt_serial_device *serial;
    
        RT_ASSERT(dev != RT_NULL);
        serial = (struct rt_serial_device *)dev;
    
        switch (cmd)
        {
            case RT_DEVICE_CTRL_SUSPEND:
                /* suspend device */
                dev->flag |= RT_DEVICE_FLAG_SUSPENDED;
                break;
    
            case RT_DEVICE_CTRL_RESUME:
                /* resume device */
                dev->flag &= ~RT_DEVICE_FLAG_SUSPENDED;
                break;
    
            case RT_DEVICE_CTRL_CONFIG:
                if (args != RT_NULL)
                {
                    struct serial_configure *pconfig = (struct serial_configure *) args;
                    if (serial->parent.ref_count)
                    {
                        /*can not change buffer size*/
                        return -RT_EBUSY;
                    }
                   /* set serial configure */
                    serial->config = *pconfig;
                    serial->ops->configure(serial,
                                        (struct serial_configure *) args);
                }
    
                break;
    
    #ifdef RT_USING_POSIX
    #ifdef RT_USING_POSIX_TERMIOS
            case TCGETA:
                {
                    struct termios *tio = (struct termios*)args;
                    if (tio == RT_NULL) return -RT_EINVAL;
    
                    tio->c_iflag = 0;
                    tio->c_oflag = 0;
                    tio->c_lflag = 0;
    
                    /* update oflag for console device */
                    if (rt_console_get_device() == dev)
                        tio->c_oflag = OPOST | ONLCR;
    
                    /* set cflag */
                    tio->c_cflag = 0;
                    if (serial->config.data_bits == DATA_BITS_5)
                        tio->c_cflag = CS5;
                    else if (serial->config.data_bits == DATA_BITS_6)
                        tio->c_cflag = CS6;
                    else if (serial->config.data_bits == DATA_BITS_7)
                        tio->c_cflag = CS7;
                    else if (serial->config.data_bits == DATA_BITS_8)
                        tio->c_cflag = CS8;
    
                    if (serial->config.stop_bits == STOP_BITS_2)
                        tio->c_cflag |= CSTOPB;
    
                    if (serial->config.parity == PARITY_EVEN)
                        tio->c_cflag |= PARENB;
                    else if (serial->config.parity == PARITY_ODD)
                        tio->c_cflag |= (PARODD | PARENB);
    
                    cfsetospeed(tio, _get_speed(serial->config.baud_rate));
                }
                break;
    
            case TCSETAW:
            case TCSETAF:
            case TCSETA:
                {
                    int baudrate;
                    struct serial_configure config;
    
                    struct termios *tio = (struct termios*)args;
                    if (tio == RT_NULL) return -RT_EINVAL;
    
                    config = serial->config;
    
                    baudrate = _get_baudrate(cfgetospeed(tio));
                    config.baud_rate = baudrate;
    
                    switch (tio->c_cflag & CSIZE)
                    {
                    case CS5:
                        config.data_bits = DATA_BITS_5;
                        break;
                    case CS6:
                        config.data_bits = DATA_BITS_6;
                        break;
                    case CS7:
                        config.data_bits = DATA_BITS_7;
                        break;
                    default:
                        config.data_bits = DATA_BITS_8;
                        break;
                    }
    
                    if (tio->c_cflag & CSTOPB) config.stop_bits = STOP_BITS_2;
                    else config.stop_bits = STOP_BITS_1;
    
                    if (tio->c_cflag & PARENB)
                    {
                        if (tio->c_cflag & PARODD) config.parity = PARITY_ODD;
                        else config.parity = PARITY_EVEN;
                    }
                    else config.parity = PARITY_NONE;
    
                    serial->ops->configure(serial, &config);
                }
                break;
            case TCFLSH:
                {
                    int queue = (int)args;
    
                    _tc_flush(serial, queue);
                }
    
                break;
            case TCXONC:
                break;
            case TIOCSWINSZ:
                {
                    struct winsize* p_winsize;
    
                    p_winsize = (struct winsize*)args;
                    rt_kprintf("x1b[8;%d;%dt", p_winsize->ws_col, p_winsize->ws_row);
                }
                break;
            case TIOCGWINSZ:
                {
                    struct winsize* p_winsize;
    
                    p_winsize = (struct winsize*)args;
                    /* TODO: get windows size from console */
                    p_winsize->ws_col = 80;
                    p_winsize->ws_row = 24;
                    p_winsize->ws_xpixel = 0;/*unused*/
                    p_winsize->ws_ypixel = 0;/*unused*/
                }
                break;
    #endif /*RT_USING_POSIX_TERMIOS*/
            case FIONREAD:
                {
                    rt_size_t recved = 0;
                    rt_base_t level;
    
                    level = rt_hw_interrupt_disable();
                    struct rt_serial_rx_fifo *rx_fifo = (struct rt_serial_rx_fifo *)serial->serial_rx;
                    recved = rt_ringbuffer_data_len(&rx_fifo->rb);
                    rt_hw_interrupt_enable(level);
    
                    *(rt_size_t *)args = recved;
                }
                break;
    #endif /*RT_USING_POSIX*/
    
            default :
                /* control device */
                ret = serial->ops->control(serial, cmd, args);
                break;
        }
    
        return ret;
    }
    
  • 相关阅读:
    struct{} //长篇更新
    channel //长篇更新
    切片 //长篇更新
    引用
    核心:数据篇
    ARM指令解析
    arm寄存器解析
    Java-Selenium,获取下拉框中的每个选项的值,并随机选择某个选项
    log4j:WARN No appenders could be found for logger (org.springframework.web.context.ContextLoader).
    eclipse安装springsource-tool-suite遇到的问题及解决方案
  • 原文地址:https://www.cnblogs.com/silencehuan/p/15308872.html
Copyright © 2020-2023  润新知