UART使用参考

Version1.0


1. 概述

本篇文档主要介绍uart口如何配置以及如何在用户层使用uart。


2. Dts配置


2.1. Demo 板支持的 UART padmux

表 2-1

UART Group Mode TX RX CTS RTS DEV
Fuart 4 PAD_KEY10 PAD_KEY11 PAD_KEY12 PAD_KEY13 /dev/ttyS2
6 PAD_GPIO5 PAD_GPIO6 PAD_GPIO7 PAD_GPIO8
10 PAD_KEY10 PAD_KEY11
12 PAD_GPIO5 PAD_GPIO6
Uart1 6 PAD_KEY6 PAD_KEY7 /dev/ttyS1
8 PAD_GPIO1 PAD_GPIO2
9 PAD_GPIO7 PAD_GPIO8
Uart2 4 PAD_KEY8 PAD_KEY9 /dev/ttyS3
6 PAD_GPIO3 PAD_GPIO4

2.2. Fuart dts配置,以 mode6 为例

  1. pioneer.dts, 其中需要将pad参数设为6

  2. 添加 Fuart padmux 复用

    修改 pioneer3-ssc020a-s01a-demo-padmux.dtsi

    Fuart 选择 Mode 6(PAD_GPIO5/PAD_GPIO6/PAD_GPIO7/PAD_GPIO8)进行输出,

    没有在其他组输出的话,需要将其他组注释掉,如下图


2.3. Uart1 dts配置,以mode8 为例

  1. pioneer.dts, 其中需要将pad参数设为8

  2. 添加 Uart1 padmux 复用

    修改 pioneer3-ssc020a-s01a-demo-padmux.dtsi

    Fuart 选择 Mode 8(PAD_GPIO1/PAD_GPIO2)进行输出,

    没有在其他组输出的话,需要将其他组注释掉,如下图


2.4. Uart2 dts配置,以mode6 为例

  1. pioneer.dts, 其中需要将pad参数设为6

  2. 添加 Uart1 padmux 复用

    修改 pioneer3-ssc020a-s01a-demo-padmux.dtsi

    Uart2 选择 Mode 6(PAD_GPIO3/PAD_GPIO4)进行输出,

    没有在其他组输出的话,需要将其他组注释掉,如下截图


3. Kernel配置

  1. 打开 kernel 对 UART 的配置

  2. 打开 SStar FUART/UART1/UART2 驱动配置


4. 用户空间如何使用uart

  1. 如何确认使用的uart pin使用的是哪个/dev/ttySx

    通过查看dts,确认uart对应的是哪路serialx,serialx对应的就是/dev/ttySx

  2. 应用层如何使用

    点击获取应用层使用参考

    如下为uart1,对应 /dev/ttyS1的自发自收的demo

    #include <stdio.h>
    #include <unistd.h>
    #include <fcntl.h>
    #include <termios.h>
    #include <pthread.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <sys/ioctl.h>
    
    int uart_send_stop = 0;
    
    int uartx_init(char *uart_name)  //"/dev/ttyS1"
    {
        int fd = -1; 
        struct termios opts;
    
        fd = open(uart_name, O_RDWR|O_NOCTTY|O_NONBLOCK);
        if (fd < 0)
        {
            perror("open ttyS2");
            return -1;
        }
    
        tcgetattr(fd, &opts); //获得串口指向termios结构的指针
    
        //设置输入/输出波特率为115200
        cfsetispeed(&opts, B115200);
        cfsetospeed(&opts, B115200);
        opts.c_cflag |= CLOCAL|CREAD; //CLOCAL 忽略modem信号线, CREAD 打开接收功能
    
        // 8N1
        opts.c_cflag &= ~PARENB; 
        opts.c_cflag &= ~CSTOPB;
        opts.c_cflag |= CS8;
    
        opts.c_cflag &= ~CRTSCTS; //无流控
    
        opts.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); //raw input
        opts.c_oflag &= ~OPOST; // raw output
    
        tcsetattr(fd, TCSANOW, &opts);
    
        return fd;
    }
    
    void *uart_send(void *arg)  
    {  
        int fd = -1;
        int loop = 10;  
        fd = *((int *)arg);
    
        while(loop--)
        {
            write(fd, "Hello world!", 12);
            sleep(1);
        }
    
        uart_send_stop = 1;
    
        pthread_exit("uart_recv exit\n");     
    }
    
    int read_datas_tty(int fd,char *rcv_buf,int sec,int usec)
    {
        int retval;
        unsigned char * tempchar2=rcv_buf;
        fd_set rfds;
        struct timeval tv;
        int ret,len=0;
        tv.tv_sec = sec;
        tv.tv_usec = usec;
        while(1)
        {
            FD_ZERO(&rfds);
            FD_SET(fd,&rfds);
            retval = select(fd+1,&rfds,NULL,NULL,&tv);
            if(retval ==-1)
            {
                perror("select()\n");
                return -1;
            }
            else if(retval)
            {
                ret= read(fd,tempchar2++,1);
                len++;
            }
            else
            {
                break;
            }
        }
    
        return len; 
    }
    
    void *uart_recv(void *arg)  
    {
        int len,fd = -1;
        char buf[256];
        fd = *((int *)arg);
    
        while(1)
        {
            len = read_datas_tty( fd,buf,0,200000);
            if(len == -1)
                break;
            else if(len == 0)
            {
    
            }
            else
            {
                printf("uart recv: %s\n",buf);
            }
    
            if(uart_send_stop == 1)
            {
                break;
            }
        }
    
        pthread_exit("uart_recv exit\n");   
    }
    
    int main(void)
    {
        int fd;
        int ret;
        void *retval;
        pthread_t th_send, th_recv;
    
        printf("Start to do the uart test!\n");
        sleep(1);
    
        fd = uartx_init("/dev/ttyS1"); //"/dev/ttyS1"
    
        pthread_create(&th_send, NULL, uart_send, (void *)(&fd));  
        pthread_create(&th_recv, NULL, uart_recv, (void *)(&fd));
    
        /* 等待两个线程结束*/  
        pthread_join(th_send, &retval);  
        pthread_join(th_recv, &retval);
    
        close(fd);
    
        return 0;
    }
    

5. uart驱动架构及debug方法

Uart驱动主要框架图如下:

从上图可以看出来驱动的主要工作就是把uart controller和对应的pad串接起来。