ARM - 海思 - HI35XX串口调试

转自: https://blog.csdn.net/li_wen01/article/details/86529523

 

我测试使用的是海思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

1
2
3
4
5
6
7
8
9
10
11
12
13
/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 种查看:

1
2
3
4
5
6
7
/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命令直接设置:

1
2
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。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
/************************************************************************************************
*****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 Can't 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; 
    //设置串口数据帧格式 
    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 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\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 haven't 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;
}  

  

 

posted on   longyue  阅读(78)  评论(0编辑  收藏  举报

相关博文:
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

导航

统计

点击右上角即可分享
微信分享提示