UART使用参考
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 为例¶
-
pioneer.dts, 其中需要将pad参数设为6
-
添加 Fuart padmux 复用
修改 pioneer3-ssc020a-s01a-demo-padmux.dtsi
Fuart 选择 Mode 6(PAD_GPIO5/PAD_GPIO6/PAD_GPIO7/PAD_GPIO8)进行输出,
没有在其他组输出的话,需要将其他组注释掉,如下图
2.3. Uart1 dts配置,以mode8 为例¶
-
pioneer.dts, 其中需要将pad参数设为8
-
添加 Uart1 padmux 复用
修改 pioneer3-ssc020a-s01a-demo-padmux.dtsi
Fuart 选择 Mode 8(PAD_GPIO1/PAD_GPIO2)进行输出,
没有在其他组输出的话,需要将其他组注释掉,如下图
2.4. Uart2 dts配置,以mode6 为例¶
-
pioneer.dts, 其中需要将pad参数设为6
-
添加 Uart1 padmux 复用
修改 pioneer3-ssc020a-s01a-demo-padmux.dtsi
Uart2 选择 Mode 6(PAD_GPIO3/PAD_GPIO4)进行输出,
没有在其他组输出的话,需要将其他组注释掉,如下截图
3. Kernel配置¶
-
打开 kernel 对 UART 的配置
-
打开 SStar FUART/UART1/UART2 驱动配置
4. 用户空间如何使用uart¶
-
如何确认使用的uart pin使用的是哪个/dev/ttySx
通过查看dts,确认uart对应的是哪路serialx,serialx对应的就是/dev/ttySx
-
应用层如何使用
如下为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串接起来。