首页 > 技术知识 > 正文

我测试使用的是海思HI3520DV400设备,它总共有三个串口,官方提供的SDK只使能了UART0,也就是调试串口。如果要使用UART1或是UART2,用户需要自己手动设置。

(一)使能串口

最直接的方式就是将设备树中对应uart的status修改为 status = “okay”。海思实际加载的串口驱动是PL011,menuconfig查看配置Device Drivers > Character devices > Serial drivers中的ARM AMBA PL011 serial port support 和 Support for console on AMBA serial port是否有选择上。重新编译内核烧入,在/dev 下可以查看是否有串口设备ttyAMA0~2。

(二)查看串口配置

可以使用linux的stty命令查看串口的配置参数。比如:stty -F /dev/ttyAMA0 -a

/dev # stty -F /dev/ttyAMA0 -a speed 115200 baud;stty: /dev/ttyAMA0 line = 0; intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = ^J; eol2 = <undef>; swtch = <undef>; start = ^Q; stop = ^S; susp = ^Z; rprnt = ^R; werase = ^W; lnext = ^V; flush = ^O; min = 1; time = 0; -parenb -parodd cs8 hupcl -cstopb cread clocal -crtscts -ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr icrnl ixon ixoff -iuclc -ixany -imaxbel -iutf8 opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0 isig icanon -iexten echo echoe echok -echonl -noflsh -xcase -tostop -echoprt -echoctl echoke /dev #

同样可以使用stty命令设置串口参数,比如:stty -F /dev/ttyAMA0 ispeed 115200 ospeed 115200 cs8

(三)查看串口数据收发

一般调试串口,我们可以将TX与RT接在一起,自己发数据给自己接收,看数据是否正常。也可以使用cat 查看串口数据或是echo发送数据。 发送数据:

echo “test 1234567890” > /dev/ttyAMA0

接收数据:

cat /dev/ttyAMA0

(四)查看串口硬件分配:

串口的硬件分配状态,比如IO和中断使用情况可以在/proc/tty/driver下的ttyAMA 种查看:

/proc/tty/driver # ls ttyAMA usbserial /proc/tty/driver # cat ttyAMA serinfo:1.0 driver revision: 0: uart:PL011 rev2 mmio:0x12080000 irq:38 tx:119786 rx:254 RTS|DTR|DSR|CD|RI 1: uart:PL011 rev2 mmio:0x12090000 irq:39 tx:48102 rx:0 CTS|DSR|CD|RI 2: uart:PL011 rev2 mmio:0x120A0000 irq:40 tx:8620 rx:55014 CTS|DSR|CD|RI

(五)注意 如果串口的配置和数据的收发命令都能够正常,但是串口的引脚没有电平变化,这个可能是串口的复用功能没有设置,需要设置一下GPIO复用为串口功能。复用功能可以在设备树dts中设置,也可以使用海思的himm命令直接设置:

himm 0x120f0100 0x01 #UART2_RXD himm 0x120f0104 0x01 #UART2_TXD

问题更新:

(1)海思uart1只能发送数据,不能正常接收数据问题

【问题背景】:设备树中正常启动uart1,配置uart1的TX, RX两个GPIO口复用为串口功能,能正常看到串口设备/dev/ttyAMA1;使用命令初始化串口1:stty -F /dev/ttyAMA1 ispeed 115200 ospeed 115200 cs8

【问题现象】:uart1只能发送数据,不能读取数据。执行 echo “test 1234567890” > /dev/ttyAMA1 可以查看到串口1有成功发送数据出去。周期向uart1发送数据,在海思端使用:cat /dev/ttyAMA1 查看串口数据接收情况,发发现接收不到数据。于此同时,数据直接RT接收到数据之后,又通过RT把全部数据发送出去了。在应用层接收不到串口的数据。

我在海思3520DV300 和HI3520DV400上测试,都是只有uart1出现该问题,uart0和uart2正常。

但是如果海思端使用microcom(busybox自带命令工具) 工具来查看数据,又能正常的收到数据。查看命令为:microcom -s 115200 /dev/ttyCOM2

【问题原因】:串口没有正确的初始化。海思的uart1 如果只设置串口波特率和位数奇偶数等信息是不能正常运行。还需要设置串口的其它属性,也就是结构体struct termios里的参数 。这里需要使用程序来初始化。

【解决方案】:使用应用程序初始化uart1。

串口程序:

/************************************************************************************************ *****Describe: This program is writen to operate HI35xx serial devices. ***** *****Email: lishuangliang@outlook.com ***** *****Author: shuang liang li ***** *****Date: 2018-09-30 ***** *************************************************************************************************/ #include<stdio.h> #include<stdlib.h> #include<unistd.h> #include<sys/types.h> #include<sys/stat.h> #include<fcntl.h> #include<termios.h> #include<errno.h> #include<string.h> #include <signal.h> //宏定义 #define HI_FALSE -1 #define HI_TRUE 0 #ifdef debugprintf #define debugpri(mesg, args…) fprintf(stderr, “[HI Serial print:%s:%d:] ” mesg “\n”, __FILE__, __LINE__, ##args) #else #define debugpri(mesg, args…) #endif int HiSerfd; void HI_Serial_Close(int fd); void Hi_sigsegv(int dummy) { if(HiSerfd > 0) HI_Serial_Close(HiSerfd); fprintf(stderr, “Hi Serial Caught SIGSEGV, Abort!\n”); fclose(stderr); abort(); } void Hi_sigterm(int dummy) { if(HiSerfd > 0) HI_Serial_Close(HiSerfd); fprintf(stderr, “Hi Serial Caught SIGTERM, Abort!\n”); fclose(stderr); exit(0); } void Hi_init_signals(void) { struct sigaction sa; sa.sa_flags = 0; sigemptyset(&sa.sa_mask); sigaddset(&sa.sa_mask, SIGSEGV); sigaddset(&sa.sa_mask, SIGTERM); sigaddset(&sa.sa_mask, SIGPIPE); sa.sa_handler = Hi_sigsegv; sigaction(SIGSEGV, &sa, NULL); sa.sa_handler = Hi_sigterm; sigaction(SIGTERM, &sa, NULL); sa.sa_handler = SIG_IGN; sigaction(SIGPIPE, &sa, NULL); } int HI_Serial_Usage(void) { printf(“Usage:\n”); printf(“\tmyhicom [-d] <HiSerialDevice> [-s] get netdeviece info [-rw] read or wite select\n”); printf(“\tmyhicom [-h] for more usage\n”); printf(“\tmyhicom [-v] the verson of the sofware\n”); printf(“\tExample:\n\tmyhicom -d /dev/ttyAMA1 -s 115200 -w HiSerial:HelloWorld\n”); } /* *Function: HI_Serial_Open(int fd,char* ComDevice) *Param: fd:file descirbe handle Serial Device: /dev/ttyAMA1 /dev/ttyAMA2 *Output: Ok or Fail */ int HI_Serial_Open(char* HiSerDevice) { int fd; fd = open(HiSerDevice, O_RDWR|O_NOCTTY|O_NDELAY); if (HI_FALSE == fd) { perror(“HiSerial Cant Open Serial HiSerDevice”); return(HI_FALSE); } //恢复串口为阻塞状态 if(fcntl(fd, F_SETFL, 0) < 0) { debugpri(“fcntl failed!\n”); return(HI_FALSE); } else { debugpri(“fcntl=%d\n”,fcntl(fd, F_SETFL,0)); } //测试是否为终端设备 if(0 == isatty(STDIN_FILENO)) { debugpri(“standard input is not a terminal device\n”); return(HI_FALSE); } else { debugpri(“isatty success!\n”); } printf(“fd->open=%d\n”,fd); return fd; } /* *Function: HI_Serial_Close(int fd) *Param: fd:file descirbe handle *Output: Null */ void HI_Serial_Close(int fd) { if(fd > 0) close(fd); return; } /* *Function: HI_Serial_Set(int fd,int speed,int flow_ctrl,int databits,int stopbits,int parity) *Param1: fd: file descirbe handle *Param2: speed: select the Serial speed.115200,19200,9600… *Param3: flow_ctrl: if use flow control *Param4: databits: data bit select *Param5: stopbits: stopbits select *Param5: parity: partiy select *Output: Ok or Fail */ int HI_Serial_Set(int fd,int speed,int flow_ctrl,int databits,int stopbits,int parity) { int i; int status; int speed_arr[] = { B115200, B19200, B9600, B4800, B2400, B1200, B300}; int name_arr[] = {115200, 19200, 9600, 4800, 2400, 1200, 300}; struct termios options; if( tcgetattr( fd,&options) != 0) { perror(“SetupSerial 1″); return(HI_FALSE); } //set buater rate for ( i= 0; i < sizeof(speed_arr) / sizeof(int); i++) { if (speed == name_arr[i]) { cfsetispeed(&options, speed_arr[i]); cfsetospeed(&options, speed_arr[i]); } } //set control model options.c_cflag |= CLOCAL; options.c_cflag |= CREAD; //set flow control switch(flow_ctrl) { case 0 ://none options.c_cflag &= ~CRTSCTS; break; case 1 ://use hard ware options.c_cflag |= CRTSCTS; break; case 2 ://use sofware options.c_cflag |= IXON | IXOFF | IXANY; break; } //select data bit options.c_cflag &= ~CSIZE; switch (databits) { case 5 : options.c_cflag |= CS5; break; case 6 : options.c_cflag |= CS6; break; case 7 : options.c_cflag |= CS7; break; case 8: options.c_cflag |= CS8; break; default: fprintf(stderr,”Unsupported data size\n”); return (HI_FALSE); } //select parity bit switch (parity) { case n: case N: options.c_cflag &= ~PARENB; options.c_iflag &= ~INPCK; break; case o: case O: options.c_cflag |= (PARODD | PARENB); options.c_iflag |= INPCK; break; case e: case E: options.c_cflag |= PARENB; options.c_cflag &= ~PARODD; options.c_iflag |= INPCK; break; case s: case S: options.c_cflag &= ~PARENB; options.c_cflag &= ~CSTOPB; break; default: fprintf(stderr,”Unsupported parity\n”); return (HI_FALSE); } // set stopbit switch (stopbits) { case 1: options.c_cflag &= ~CSTOPB; break; case 2: options.c_cflag |= CSTOPB; break; default: fprintf(stderr,”Unsupported stop bits\n”); return (HI_FALSE); } //set raw data output options.c_oflag &= ~OPOST; options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); //options.c_lflag &= ~(ISIG | ICANON); //set wait time options.c_cc[VTIME] = 1; options.c_cc[VMIN] = 1; tcflush(fd,TCIFLUSH); //set the attribute to HiSerial device if (tcsetattr(fd,TCSANOW,&options) != 0) { perror(“com set error!\n”); return (HI_FALSE); } return (HI_TRUE); } /* *Function: HI_Serial_Init(int fd, int speed,int flow_ctrl,int databits,int stopbits,int parity) *Param: … *Output: HI_TRUE or HI_FALSE */ int HI_Serial_Init(int fd, int speed,int flow_ctrl,int databits,int stopbits,int parity) { int err; //设置串口[数据帧](https://www.ebaina.com/resources/240000028176 “数据帧”)格式 if (HI_Serial_Set(fd,speed,flow_ctrl,databits,stopbits,parity) == HI_FALSE) { return HI_FALSE; } else { return HI_TRUE; } } /* *Function: HI_Serial_Send(int fd, char *send_buf,int data_len) *Param1: fd:file descirbe handle *Param2: send_buf:Data to be send *Param2: data_len:Data len *Output: Data send len or HI_FALSE */ int HI_Serial_Send(int fd, char *send_buf,int data_len) { int len = 0; len = write(fd,send_buf,data_len); if (len == data_len ) { debugpri(“send data is %s\n”,send_buf); return len; } else { tcflush(fd,TCOFLUSH); return HI_FALSE; } } /* *Function: HI_Serial_Recv(int fd, char *rcv_buf,int data_len) *Param1: fd:file descirbe handle *Param2: rcv_buf:receive Data *Param2: data_len:receive Data len *Output: Receive Data len or HI_FALSE */ int HI_Serial_Recv(int fd, char *rcv_buf,int data_len) { int len,fs_sel; fd_set fs_read; struct timeval time; FD_ZERO(&fs_read); FD_SET(fd,&fs_read); time.tv_sec = 30; time.tv_usec = 0; //select fdset fs_sel = select(fd+1,&fs_read,NULL,NULL,&time); if(fs_sel) { len = read(fd,rcv_buf,data_len); debugpri(“HiSeral Receive Data = %s len = %d fs_sel = %d\n”,rcv_buf,len,fs_sel); return len; } else { debugpri(“Hiserial havent data receive!”); return HI_FALSE; } } int main ( int argc, char *argv[] ) { int cmd; int len; //extern char *optarg; //extern int optind, opterr, optopt; char HiSerialDev[32]=”/dev/ttyAMA1″; char sendbuf[1024]={0}; char recvbuf[1024]={0}; int SerialSpeed = 115200; Hi_init_signals(); if(argc == 1) { HI_Serial_Usage(); exit(0); } else { while ((cmd = getopt(argc, argv, “:d:s:rw:hv”)) != -1) { switch (cmd) { case h: HI_Serial_Usage(); break; case v: printf(“myHicom –Verson V1.0.0\n”); break; case d: //printf(“catch -d %s \n”,optarg); memset(HiSerialDev,0,sizeof(HiSerialDev)); sprintf(HiSerialDev,”%s”,optarg); printf(“myHicom HiSerialDev %s\n”,optarg); break; case s: SerialSpeed = atoi(optarg); printf(“myHicom speed %d\n”,SerialSpeed); break; case r: debugpri(“myHicom read\n”); HiSerfd = HI_Serial_Open(HiSerialDev); HI_Serial_Init(HiSerfd,SerialSpeed,0,8,1,N); while(1) { len = HI_Serial_Recv(HiSerfd, recvbuf,sizeof(recvbuf)); if(len > 0) { recvbuf[len] = \0; printf(“Hiserial receive data: %s\n”,recvbuf); memset(recvbuf,0,sizeof(recvbuf)); //break; } else { debugpri(“Hiserial havent data receive \n”); } sleep(2); }; break; case w: debugpri(“myHicom write %s\n”,optarg); HiSerfd = HI_Serial_Open(HiSerialDev); printf(“fd = %d device = %s speed = %d\n”,HiSerfd,HiSerialDev,SerialSpeed); HI_Serial_Init(HiSerfd,SerialSpeed,0,8,1,N); sprintf(sendbuf,”%s\n”,optarg); HI_Serial_Send(HiSerfd, sendbuf, strlen(sendbuf)+1); if(HiSerfd > 0) HI_Serial_Close(HiSerfd); break; case :: printf (“option: -%c missing argument. -h for help.\n”,(char)optopt); break; case ?: printf(“Unknown option: -%c\n”,(char)optopt); break; default: exit(0); } } } return 0; }
<

原文链接:https://blog.csdn.net/li_wen01/article/details/86529523

猜你喜欢