配置驱动选项

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函数是否被调用,进一步查找原因。

模组uart调试总结-LMLPHP

 

软件回环测试

2.1 如果成功产生了UART设备节点,可通过软件回环测试确认UART驱动程序功能是否正常。比如ttyHS0,我们先将loopback.0值设置为1,打开该UART回环测试:

$ echo 1 > /sys/kernel/debug/msm_serial_hs/loopback.0
   
   

回环测试程序代码:


   
   
  1. #include<stdio.h>
  2. #include<stdlib.h>
  3. #include<string.h>
  4. #include<sys/types.h>
  5. #include<sys/stat.h>
  6. #include<fcntl.h>
  7. #include<unistd.h>
  8. #include<termios.h>
  9. #include<string.h>
  10. int set_opt(int fd,int nSpeed, int nBits, char nEvent, int nStop)
  11. {
  12. struct termios newtio,oldtio;
  13. if( tcgetattr( fd,&oldtio) != 0) {
  14. perror( "tcgetattr error");
  15. return -1;
  16. }
  17. bzero( &newtio, sizeof( newtio ) );
  18. newtio.c_cflag |= CLOCAL | CREAD;
  19. newtio.c_cflag &= ~CSIZE;
  20. switch( nBits )
  21. {
  22. case 7:
  23. newtio.c_cflag |= CS7;
  24. break;
  25. case 8:
  26. newtio.c_cflag |= CS8;
  27. break;
  28. }
  29. switch( nEvent )
  30. {
  31. case 'O':
  32. newtio.c_cflag |= PARENB;
  33. newtio.c_cflag |= PARODD;
  34. newtio.c_iflag |= (INPCK | ISTRIP);
  35. break;
  36. case 'E':
  37. newtio.c_iflag |= (INPCK | ISTRIP);
  38. newtio.c_cflag |= PARENB;
  39. newtio.c_cflag &= ~PARODD;
  40. break;
  41. case 'N':
  42. newtio.c_cflag &= ~PARENB;
  43. break;
  44. }
  45. switch( nSpeed )
  46. {
  47. case 2400:
  48. cfsetispeed(&newtio, B2400);
  49. cfsetospeed(&newtio, B2400);
  50. break;
  51. case 4800:
  52. cfsetispeed(&newtio, B4800);
  53. cfsetospeed(&newtio, B4800);
  54. break;
  55. case 9600:
  56. cfsetispeed(&newtio, B9600);
  57. cfsetospeed(&newtio, B9600);
  58. break;
  59. case 115200:
  60. cfsetispeed(&newtio, B115200);
  61. cfsetospeed(&newtio, B115200);
  62. break;
  63. case 460800:
  64. cfsetispeed(&newtio, B460800);
  65. cfsetospeed(&newtio, B460800);
  66. break;
  67. default:
  68. cfsetispeed(&newtio, B9600);
  69. cfsetospeed(&newtio, B9600);
  70. break;
  71. }
  72. if( nStop == 1){
  73. newtio.c_cflag &= ~CSTOPB;
  74. } else if ( nStop == 2 ){
  75. newtio.c_cflag |= CSTOPB;
  76. }
  77. newtio.c_cc[VTIME] = 0;
  78. newtio.c_cc[VMIN] = 0;
  79. tcflush(fd,TCIFLUSH);
  80. if(( tcsetattr(fd,TCSANOW,&newtio))!= 0)
  81. {
  82. perror( "set error");
  83. return -1;
  84. }
  85. return 0;
  86. }
  87. int main(int argc,char *argv[])
  88. {
  89. int fd,ret_set,ret_read,ret;
  90. char buf_read[ 100];
  91. char tty[ 20]= "/dev/";
  92. if( 4 == argc)
  93. {
  94. strcat(tty,argv[ 1]);
  95. fd = open(tty, O_RDWR);
  96. if(fd == -1)
  97. {
  98. printf( "Open %s failed! Exit!\n",tty);
  99. exit( 1);
  100. }
  101. printf( "open %s successfully!\n",tty);
  102. ret_set = set_opt(fd, atoi(argv[ 2]), 8, 'N', 1);
  103. if (ret_set == -1)
  104. {
  105. printf( "Set %s failed! Exit!\n",tty);
  106. exit( 1);
  107. }
  108. printf( "Set %s successfully!\n",tty);
  109. printf( "Baud rate: %s\n",argv[ 2]);
  110. printf( "Data: %s\n",argv[ 3]);
  111. while ( 1)
  112. {
  113. memset(buf_read, 0, sizeof(buf_read));
  114. ret = write(fd, argv[ 3], 100);
  115. if( ret > 0){
  116. printf( "Write data: %s\n",argv[ 3]);
  117. } else{
  118. printf( "Write data failed! Exit!\n");
  119. exit( 1);
  120. }
  121. ret_read = read(fd, buf_read, 100);
  122. if(ret_read > 0){
  123. printf( "Read data: %s\n\n", buf_read);
  124. }
  125. sleep( 3);
  126. }
  127. close(fd);
  128. } else{
  129. printf( "Usage: uart [tty node] [baud rate] [data]\n");
  130. printf( " Sample: uart ttyHSL1 115200 test\n");
  131. }
  132. return 0;
  133. }
模组uart调试总结-LMLPHP

测试程序github地址:https://github.com/IOT-er/uart

交叉编译得到执行文件uart:

$ arm-linux-gcc -g uart.c -o uart
   
   

运行uart进行回环测试:

模组uart调试总结-LMLPHP

可以看到UART1成功收到了发送的 hello字符。

还有一种简单的软件测试方式:


   
   
  1. adb shell
  2. echo 1 > /sys /kernel /debug /msm_serial_hs /loopback. 0 / /打开回环开关
  3. cat /sys /kernel /debug /msm_serial_hs /loopback. 0 / /确保已经打开回环开关了
  4. adb shell
  5. cat /dev /ttyHS 0
  6. adb shell
  7. 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短接后,检查步骤如下,如果管脚信号测试通过,则串口功能基本调试成功。此方法的优点是无需上位机串口助手的配合,在串口模块到位之前提前完成接口调试工作。


   
   
  1. adb shell
  2. echo 1 > /sys /kernel /debug /msm_serial_hs /loopback. 0 / /打开回环开关
  3. cat /sys /kernel /debug /msm_serial_hs /loopback. 0 / /确保已经打开回环开关了
  4. adb shell
  5. cat /dev /ttyHS 0
  6. adb shell
  7. echo "This Is A Test" > /dev /ttyHS 0 - >Transfer data

 

05-17 01:24