配置驱动选项
1.1 首先通过原理图确定其串口号,比如UART1、UART3_HS,同时查看该串口引脚是否有复用功能,比如用作SIM卡引脚。如果有复用,需要在设备树配置中取消复用功能的选项,然后选中串口功能,高通平台设备树路径为:kernel\msm-xxx\arch\arm\boot\dts\qcom或者kernel\msm-xxx\arch\arm64\boot\dts\qcom,这个路径视arm的位数而定。
1.2 编译运行内核,如果UART1驱动加载成功会在/dev目录下产生相应UART设备节点。以高通sdx20为例,系统启动之后在/dev下有两个ttyHSL设备节点:ttyHS0、ttyHSL0。输入命令(cat /proc/tty/driver/msm_serial_hs)可以显示设备节点详细信息,其中通过地址和datasheet对比即可知道UART对应的设备节点。同时通过who命令可查看当前终端tty信息。如果UART设备节点未产生,可在其相应驱动程序xx_probe函数中添加打印,查看xx_probe函数是否被调用,进一步查找原因。
软件回环测试
2.1 如果成功产生了UART设备节点,可通过软件回环测试确认UART驱动程序功能是否正常。比如ttyHS0,我们先将loopback.0值设置为1,打开该UART回环测试:
$ echo 1 > /sys/kernel/debug/msm_serial_hs/loopback.0
回环测试程序代码:
-
#include<stdio.h>
-
#include<stdlib.h>
-
#include<string.h>
-
#include<sys/types.h>
-
#include<sys/stat.h>
-
#include<fcntl.h>
-
#include<unistd.h>
-
#include<termios.h>
-
#include<string.h>
-
-
int set_opt(int fd,int nSpeed, int nBits, char nEvent, int nStop)
-
{
-
struct
termios newtio,oldtio;
-
if(
tcgetattr( fd,&oldtio) !=
0) {
-
perror(
"tcgetattr error");
-
return
-1;
-
}
-
bzero( &newtio,
sizeof( newtio ) );
-
newtio.c_cflag |= CLOCAL | CREAD;
-
newtio.c_cflag &= ~CSIZE;
-
-
switch( nBits )
-
{
-
case
7:
-
newtio.c_cflag |= CS7;
-
break;
-
case
8:
-
newtio.c_cflag |= CS8;
-
break;
-
}
-
-
switch( nEvent )
-
{
-
case
'O':
-
newtio.c_cflag |= PARENB;
-
newtio.c_cflag |= PARODD;
-
newtio.c_iflag |= (INPCK | ISTRIP);
-
break;
-
case
'E':
-
newtio.c_iflag |= (INPCK | ISTRIP);
-
newtio.c_cflag |= PARENB;
-
newtio.c_cflag &= ~PARODD;
-
break;
-
case
'N':
-
newtio.c_cflag &= ~PARENB;
-
break;
-
}
-
-
switch( nSpeed )
-
{
-
case
2400:
-
cfsetispeed(&newtio, B2400);
-
cfsetospeed(&newtio, B2400);
-
break;
-
case
4800:
-
cfsetispeed(&newtio, B4800);
-
cfsetospeed(&newtio, B4800);
-
break;
-
case
9600:
-
cfsetispeed(&newtio, B9600);
-
cfsetospeed(&newtio, B9600);
-
break;
-
case
115200:
-
cfsetispeed(&newtio, B115200);
-
cfsetospeed(&newtio, B115200);
-
break;
-
case
460800:
-
cfsetispeed(&newtio, B460800);
-
cfsetospeed(&newtio, B460800);
-
break;
-
default:
-
cfsetispeed(&newtio, B9600);
-
cfsetospeed(&newtio, B9600);
-
break;
-
}
-
-
if( nStop ==
1){
-
newtio.c_cflag &= ~CSTOPB;
-
}
else
if ( nStop ==
2 ){
-
newtio.c_cflag |= CSTOPB;
-
}
-
newtio.c_cc[VTIME] =
0;
-
newtio.c_cc[VMIN] =
0;
-
tcflush(fd,TCIFLUSH);
-
if((
tcsetattr(fd,TCSANOW,&newtio))!=
0)
-
{
-
perror(
"set error");
-
return
-1;
-
}
-
return
0;
-
}
-
-
int main(int argc,char *argv[])
-
{
-
int fd,ret_set,ret_read,ret;
-
char buf_read[
100];
-
char tty[
20]=
"/dev/";
-
if(
4 == argc)
-
{
-
strcat(tty,argv[
1]);
-
fd =
open(tty, O_RDWR);
-
if(fd ==
-1)
-
{
-
printf(
"Open %s failed! Exit!\n",tty);
-
exit(
1);
-
}
-
printf(
"open %s successfully!\n",tty);
-
-
ret_set =
set_opt(fd,
atoi(argv[
2]),
8,
'N',
1);
-
if (ret_set ==
-1)
-
{
-
printf(
"Set %s failed! Exit!\n",tty);
-
exit(
1);
-
}
-
printf(
"Set %s successfully!\n",tty);
-
printf(
"Baud rate: %s\n",argv[
2]);
-
printf(
"Data: %s\n",argv[
3]);
-
while (
1)
-
{
-
memset(buf_read,
0,
sizeof(buf_read));
-
ret =
write(fd, argv[
3],
100);
-
if( ret >
0){
-
printf(
"Write data: %s\n",argv[
3]);
-
}
else{
-
printf(
"Write data failed! Exit!\n");
-
exit(
1);
-
}
-
ret_read =
read(fd, buf_read,
100);
-
if(ret_read >
0){
-
printf(
"Read data: %s\n\n", buf_read);
-
}
-
sleep(
3);
-
}
-
close(fd);
-
}
else{
-
printf(
"Usage: uart [tty node] [baud rate] [data]\n");
-
printf(
" Sample: uart ttyHSL1 115200 test\n");
-
}
-
return
0;
-
}
测试程序github地址:https://github.com/IOT-er/uart
交叉编译得到执行文件uart:
$ arm-linux-gcc -g uart.c -o uart
运行uart进行回环测试:
可以看到UART1成功收到了发送的 hello字符。
还有一种简单的软件测试方式:
-
adb shell
-
echo 1
>
/sys
/kernel
/debug
/msm_serial_hs
/loopback.
0
/
/打开回环开关
-
cat
/sys
/kernel
/debug
/msm_serial_hs
/loopback.
0
/
/确保已经打开回环开关了
-
-
adb shell
-
cat
/dev
/ttyHS
0
-
-
adb shell
-
echo
"This Is A Test"
>
/dev
/ttyHS
0 -
>Transfer
data
管脚信号测试
软件回环测试通过之后,查看uart gpio是否ok:tx高电平(uart空闲时tx传输二进制1)、rfr为低电平,rx,cts为输入。如果tx为低电平,那么gpio肯定没有配置好,再次检查gpio配置问题,还有确认硬件线路无误后最可能的原因是TX管脚被其他功能占用。如果以上2步都ok,那么UART应该ok了。再次检查将UART1的RX、TX管脚短接,关闭软件回环,使用uart程序进行自收发测试。关闭软件回环:
$ echo 0 > /sys/kernel/debug/msm_serial_hs/loopback.0
将rx和tx短接后,检查步骤如下,如果管脚信号测试通过,则串口功能基本调试成功。此方法的优点是无需上位机串口助手的配合,在串口模块到位之前提前完成接口调试工作。
-
adb shell
-
echo 1
>
/sys
/kernel
/debug
/msm_serial_hs
/loopback.
0
/
/打开回环开关
-
cat
/sys
/kernel
/debug
/msm_serial_hs
/loopback.
0
/
/确保已经打开回环开关了
-
-
adb shell
-
cat
/dev
/ttyHS
0
-
-
adb shell
-
echo
"This Is A Test"
>
/dev
/ttyHS
0 -
>Transfer
data