[海思] HI3531D串口调试

[海思] HI3531D串口调试

背景

  • 根据需求,我需要测试和使用海思3531d的串口1和串口3,而板子默认是只有调试串口UART0,因此需要将其他的串口进行使能和配置

步骤

  1. 修改设备树,使能其他串口

    # 修改板子相关的dts,这里为hisi3531d-demb.dts
    $ vim arch/arm/boot/dts/hisi3531d-demb.dts
    ...
    &uart0 { 
    	status = "okay";
    };
    
    &uart1 { 
    	status = "okay";
    };
    # 这里我不用打开串口2,需要打开过程类似
    &uart3 {
    	status = "okay";
    }; 
    ...
    
    #编译内核并烧写到板子上
    $ make ARCH=arm CROSS_COMPILE=arm-hisiv500-linux- uImage
    
    # 烧写内核后查看是否有其他节点 AMA0~2
    $ ls /dev/ttyAMA*
    /dev/ttyAMA0  /dev/ttyAMA1  /dev/ttyAMA2(这个是串口三的节点)
    
  2. 引脚复用

    # uart1
    $ himm 0x120f0208 0x2
    $ himm 0x120f020C 0x2
    
    # uart3
    $ himm 0x120f0218 0x1
    $ himm 0x120f021C 0x1
    
  3. 简单测试输入输出

    #/dev/ttyAMA0是调试串口,因此只要启动时有打印,就是可以用的
    #测试/dev/ttyAMA1
    #发送数据(PC串口助手接收)
    $ echo 111 > /dev/ttyAMA1
    #接收数据(PC串口助手发送)
    $ cat /dev/ttyAMA1
    
  4. 查看串口的硬件分配和发送接收状态

    $ cat /proc/tty/driver/ttyAMA
    

问题与解决方案

  • 现象:在uart1和uart3发送数据给PC时,PC的串口调试助手可以收到消息,但在接收数据(cat /dev/ttyAMA1)时,PC串口助手发送的数据没有在终端上显示,而是原路返回到PC串口助手上显示,导致应用程序读不到

  • 原因:串口没有正确初始化,即结构体struct termios里的参数没有初始化好

  • 解决方案:写一个应用程序初始化并测试,下列参考代码在板子上可以正确运行

    参考链接:(1条消息) 海思HI35XX串口调试_Biao-CSDN博客

    #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 "
    ", __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!
    ");
    	fclose(stderr);
    	abort();
    }
     
    void Hi_sigterm(int dummy)
    {
    	if(HiSerfd > 0)
    		HI_Serial_Close(HiSerfd);
    	fprintf(stderr, "Hi Serial Caught SIGTERM, Abort!
    ");
    	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:
    ");
        printf("	myhicom [-d] <HiSerialDevice> [-s] get netdeviece info [-rw] read or wite select
    ");
        printf("	myhicom [-h] for more usage
    ");
        printf("	myhicom [-v] the verson of the sofware
    ");
    	printf("	Example:
    	myhicom -d /dev/ttyAMA1 -s 115200 -w HiSerial:HelloWorld
    ");
    }
     
    /*
    *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 Can't Open Serial HiSerDevice");  
    		return(HI_FALSE);  
    	}  
    	//恢复串口为阻塞状态                                 
    	if(fcntl(fd, F_SETFL, 0) < 0)  
    	{  
    		debugpri("fcntl failed!
    ");  
    		return(HI_FALSE);  
    	}       
    	else  
    	{  
    		debugpri("fcntl=%d
    ",fcntl(fd, F_SETFL,0));  
    	}  
    	//测试是否为终端设备      
    	if(0 == isatty(STDIN_FILENO))  
    	{  
    		debugpri("standard input is not a terminal device
    ");  
    		return(HI_FALSE);  
    	}  
    	else  
    	{  
    		debugpri("isatty success!
    ");  
    	}                
    	printf("fd->open=%d
    ",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
    ");  
                     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
    ");      
                     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
    ");   
                           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!
    ");    
    		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;  
        //设置串口数据帧格式  
        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
    ",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
    ",rcv_buf,len,fs_sel);  
    		return len;  
    	}  
        else  
    	{  
    		debugpri("Hiserial haven't 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
    ");
    					break;
    				case 'd':
    					//printf("catch -d %s 
    ",optarg);
    					memset(HiSerialDev,0,sizeof(HiSerialDev));
    					sprintf(HiSerialDev,"%s",optarg);
    					printf("myHicom HiSerialDev %s
    ",optarg);
    					break;
    				case 's':
    					SerialSpeed = atoi(optarg);
    					printf("myHicom speed %d
    ",SerialSpeed);
    					break;
    				case 'r':					
    					 debugpri("myHicom read
    ");
    					 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] = '';  
    							printf("Hiserial receive data: %s
    ",recvbuf);  
    							memset(recvbuf,0,sizeof(recvbuf));
    							//break;  
    						}  
    						else  
    						{  
    							debugpri("Hiserial haven't data receive 
    ");  
    						}  						 
    					 };		
    					 break;
    				case 'w':
    					 debugpri("myHicom write %s
    ",optarg);
    					 HiSerfd = HI_Serial_Open(HiSerialDev);
    					 printf("fd = %d device = %s speed = %d
    ",HiSerfd,HiSerialDev,SerialSpeed);
    					 HI_Serial_Init(HiSerfd,SerialSpeed,0,8,1,'N');					 
    					 sprintf(sendbuf,"%s
    ",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.
    ",(char)optopt);
                        break;
    			    case '?':
                        printf("Unknown option: -%c
    ",(char)optopt);
                        break;
    				default:
    					exit(0);
    			}
    		}	
    	}	
    	return 0;
    }	
    
    # 测试发送和接收
    $ ./myhicom -d /dev/ttyAMA1 -s 115200 -r
    $ ./myhicom -d /dev/ttyAMA1 -s 115200 -w helloworld
    
原文地址:https://www.cnblogs.com/chenj-nry/p/15189303.html