海思HI 35 XXシリアルデバッグ


私がテストして使ったのは海思HI 3520 DV 400設備で、それは全部で3つのシリアルポートがあって、公式に提供したSDKはUART 0だけを使用することができて、つまりシリアルポートをデバッグします.UART 1またはUART 2を使用する場合は、ユーザーが手動で設定する必要があります.
(一)イネーブルシリアルポート
    最も直接的な方法は、デバイスツリーのuartに対応するstatusをstatus=「okay」に変更することです.海思が実際にロードしたシリアルドライバはPL 011で、menuconfigはデバイスDrivers>Character devices>Serial driversのARM AMBA PL 011 serial port supportとSupport for console on AMBA serial portの選択があるかどうかを表示します.カーネルを再コンパイルして焼入し、/devでシリアルポートデバイスttyAMA 0~2があるかどうかを確認できます.
(二)シリアルポート構成の表示
linuxのsttyコマンドを使用して、シリアルポートの構成パラメータを表示できます.例えばstty-F/dev/ttyAMA 0-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 = ; swtch = ; 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/ttyAMA 0 ispeed 115200 ospeed 115200 cs 8などのシリアルポートパラメータを設定できます. 
(三)シリアルポートデータ送受信の表示
    一般的にシリアルポートをデバッグして、私达はTXとRTをつなぎ合わせて、自分でデータを送って自分で受信して、データが正常かどうかを见ます.catを使用してシリアルポートデータまたはecho送信データを表示することもできます.送信データ:
    echo"test 1234567890">/dev/ttyAMA 0受信データ: 
    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)海思uart 1はデータしか送信できず、データを正常に受信できない問題
    【問題背景】:設備ツリーでuart 1を正常に起動し、uart 1のTXを配置し、RXの2つのGPIOポートをシリアルポート機能に多重化し、シリアルポート設備/dev/ttyAMA 1を正常に見ることができる.コマンドを使用してシリアルポート1:stty-F/dev/ttyAMA 1を初期化 ispeed 115200 ospeed 115200 cs8 
    【問題現象】:uart 1はデータしか送信できず、データを読み取ることができません.echo"test 1234567890">/dev/ttyAMA 1の実行  シリアルポート1が正常にデータを送信したことを確認できます.周期的にuart 1にデータを送信し、海思端でcat/dev/ttyAMA 1を使用してシリアルポートデータの受信状況を確認し、受信できないことを発見した.同時に、データは直接RTでデータを受信した後、RTですべてのデータを送信した.アプリケーション層ではシリアルポートのデータが受信されません.
    私は海思3520 DV 300とHI 3520 DV 400でテストして、すべてuart 1だけがこの問題が発生して、uart 0とuart 2は正常です. 
    しかし、海思端がmicrocom(busyboxにコマンドツールが付属している)を使用すると ツールを使用してデータを表示し、正常にデータを受信できます.表示コマンド:microcom-s 115200/dev/ttyCOM 2
    【問題原因】:シリアルポートが正しく初期化されていません.ハイスのuart 1はシリアルポートボーレートやビット数奇偶数などの情報だけを設定すると正常に動作しません.シリアルポートの他のプロパティ、すなわち構造体struct termiosのパラメータを設定する必要があります.ここではプログラムを使用して初期化する必要があります.
    【解決策】:uart 1をアプリケーションで初期化します.
    
次のシリアル・ポート・プログラムのソースは、次のとおりです.https://blog.csdn.net/dosthing/article/details/82951207 ;私の開発ボードでテストは正常です.
/************************************************************************************************
*****Describe: This program is writen to operate HI35xx serial devices.                     *****
*****Email: [email protected]                                              			*****
*****Author: shuang liang li																*****
*****Date: 2018-09-30																		*****
*************************************************************************************************/

#include       
#include     
#include    
#include   
#include     
#include     
#include    
#include      
#include 
#include   

//     
#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("\tmyhicom [-d] [-s] get netdeviece info [-rw] read or wite select
"); printf("\tmyhicom [-h] for more usage
"); printf("\tmyhicom [-v] the verson of the sofware
"); printf("\tExample:
\tmyhicom -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] = '\0'; printf("Hiserial receive data: %s
",recvbuf); memset(recvbuf,0,sizeof(recvbuf)); //break; } else { debugpri("Hiserial haven't data receive
"); } sleep(2); }; 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; }