Linux UART接口调试技巧

2023-05-16

在嵌入式项目中,UART接口的使用频率很高,多种模块(2G通信模组、蓝牙模块,等等)都会通过UART接口与主控MCU相连。本文将梳理UART接口调试流程,为调试工作提供参考,解决调试过程中可能遇到的问题,快速完成UART接口调试,实现模块功能。

配置驱动选项

首先查看原理图确认串口号,比如UART1,同时查看该串口引脚是否有复用功能,比如用作SD卡接口。如果有复用,需要在内核配置中取消复用功能的选项。然后选中串口功能,大致的路径为

Device Drivers > Character devices > Serial drivers

不同厂家提供的BSP有细微差别,具体路径视情况而定。在内核根目录输入make menuconfig打开内核配置界面,选中UART1。以nuc970 为例,配置如下:

$ make menuconfig

这里写图片描述

产生UART设备节点

编译运行内核,如果UART1驱动加载成功会在/dev目录下产生相应UART设备节点。以高通mdm9x07为例:

这里写图片描述

系统启动之后在/dev下有两个ttyHSL设备节点:ttyHSL0、ttyHSL1。

$ cat /proc/tty/driver/msm_serial_hsl

输入该命令可以显示设备节点详细信息,其中通过地址(0x078B3000)与data sheet对比即可确认UART1对应的设备节点为/dev/ttyHSL1。
同时通过who命令可查看当前终端tty信息。

$ who
root ttyHSL0 00:00 Jan 6 00:02:00

发现/dev/ttyHSL0为调试串口。
如果UART设备节点未产生,可在其相应驱动程序xx_probe函数中添加打印,查看xx_probe函数是否被调用,进一步查找原因。

软件回环测试

如果成功产生了UART设备节点,可通过软件回环测试确认UART驱动程序功能是否正常。测试步骤:

这里写图片描述

进入loopback文件所在目录:

$ cd /sys/kernel/debug/msm_serial_hsl

将loopback.1值设置为1,打开UART1回环测试。

$ echo 1 > loopback.1

回环测试程序代码:

#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字符。

管脚信号测试

软件回环测试通过之后,将UART1的RX、TX管脚短接,关闭软件回环,使用uart程序进行自收发测试。
关闭软件回环:

$ echo 0 > loopback.1

此时有可能出现的问题是TX管脚无信号输出,确认硬件线路无误后最可能的原因是TX管脚被其他功能占用。
如果管脚信号测试通过,则串口功能基本调试成功。此方法的优点是无需上位机串口助手的配合,在串口模块到位之前提前完成接口调试工作。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Linux UART接口调试技巧 的相关文章

  • 为什么我收到的数据包数据大小大于mss?

    我在两台 PC 上使用 ifconfig ethX mtu 300 修改了 MTU 并使用 netperf 测试网络 我用 WireShark 嗅探了 SYN 数据包中的 MSS 260 但我得到了一些大于 260 的数据包 为什么 嗅探器
  • 何时使用 pthread 条件变量?

    线程问题 看来 只有在其他线程调用 pthread cond notify 之前调用 pthread cond wait 时 条件变量才起作用 如果在等待之前发生通知 那么等待将被卡住 我的问题是 什么时候应该使用条件变量 调度程序可以抢占
  • 为什么我收到“无法进行二进制日志记录”的信息。在我的 MySQL 服务器上?

    当我今天启动 MySQL 服务器并尝试使用以下命令进行一些更改时用于 MySQL 的 Toad http www quest com toad for mysql 我收到此消息 MySQL 数据库错误 无法进行二进制日志记录 消息 交易级别
  • awk 子串单个字符

    这是columns txt aaa bbb 3 ccc ddd 2 eee fff 1 3 3 g 3 hhh i jjj 3 kkk ll 3 mm nn oo 3 我可以找到第二列以 b 开头的行 awk if substr 2 1 1
  • 无法加载 JavaHL 库。- linux/eclipse

    在尝试安装 Subversion 插件时 当 Eclipse 启动时出现此错误 Failed to load JavaHL Library These are the errors that were encountered no libs
  • 强制卸载 NFS 安装目录 [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 Locked 这个问题及其答案是locked help locked posts因为这个问题是题外话 但却具有历史意义 目前不接受新的答案
  • 通过特定分隔符删除字符串

    我的文件中有几列 其中第二列有 分隔符 我想删除第二列中的第一个 第三个和第四个字符串 并将第二个字符串留在该列中 但我有正常的分隔符空间 所以我不知道 input 22 16050075 A G 16050075 A G 22 16050
  • 从 csv 文件中删除特定列,保持输出上的相同结构[重复]

    这个问题在这里已经有答案了 我想删除第 3 列并在输出文件中保留相同的结构 输入文件 12 10 10 10 10 1 12 23 1 45 6 7 11 2 33 45 1 2 1 2 34 5 6 I tried awk F 3 fil
  • 如何在bash中使用jq从变量中包含的json中提取值

    我正在编写一个 bash 脚本 其中存储了一个 json 值 现在我想使用 Jq 提取该 json 中的值 使用的代码是 json val code lyz1To6ZTWClDHSiaeXyxg redirect to http examp
  • Android Things 5​​.1 - 9 位 UART

    我正在尝试使用 Android Things 支持 9 位 UART 当我尝试将数据大小设置为 9 时 我收到 IO 异常 唯一有效的配置是 7 位和 8 位 我知道可以使用奇偶校验错误中断进行 9 位模拟 但在 Android 上 我没有
  • 我可以从命令行打印 html 文件(带有图像、css)吗?

    我想从脚本中打印带有图像的样式化 html 页面 谁能建议一个开源解决方案 我使用的是 Linux Ubuntu 8 04 但也对其他操作系统的解决方案感兴趣 你可以给html2ps http user it uu se jan html2
  • 从 Python 调用 PARI/GP

    我想打电话PARI GP http pari math u bordeaux fr dochtml gpman html仅从Python计算函数nextprime n 对于不同的n是我定义的 不幸的是我无法得到帕里蟒蛇 http code
  • fopen 不返回

    我在 C 程序中使用 fopen 以只读模式 r 打开文件 但就我而言 我观察到 fopen 调用没有返回 它不返回 NULL 或有效指针 执行在 fopen 调用时被阻止 文件补丁绝对正确 我已经验证过 并且不存在与权限相关的问题 任何人
  • 如何使用GDB修改内存内容?

    我知道我们可以使用几个命令来访问和读取内存 例如 print p x 但是如何更改任何特定位置的内存内容 在 GDB 中调试时 最简单的是设置程序变量 参见GDB 分配 http sourceware org gdb current onl
  • linux perf:如何解释和查找热点

    我尝试了linux perf https perf wiki kernel org index php Main Page今天很实用 但在解释其结果时遇到了困难 我习惯了 valgrind 的 callgrind 这当然是与基于采样的 pe
  • nslookup 报告“无法解析 '(null)': 名称无法解析”,尽管它成功解析了 DNS 名称

    我在 ubuntu 上 并且正在运行 docker 默认桥接网络 我有 Zookeeper kafka 的容器化版本 以及我编写的与 kafka 对话的应用程序 I do a docker exec it
  • 如何在 Linux shell 中将十六进制转换为 ASCII 字符?

    假设我有一个字符串5a 这是 ASCII 字母的十六进制表示Z 我需要找到一个 Linux shell 命令 它将接受一个十六进制字符串并输出该十六进制字符串代表的 ASCII 字符 所以如果我这样做 echo 5a command im
  • PHP 从命令行启动 gui 程序,但 apache 不启动

    首先 我阅读了有类似问题的人的一些帖子 但所有答案都没有超出导出 DISPLAY 0 0 和 xauth cookies 这是我的问题 提前感谢您的宝贵时间 我开发了一个小库 它使用 OpenGL 和 GLSL 渲染货架 过去几天我将它包装
  • 如何在apache 2.4.6上安装apxs模块

    我刚刚用过apt get update我的 apache 已更新为2 4 6 我想安装 apxs 来编译模块 但收到此错误 The following packages have unmet dependencies apache2 pre
  • ubuntu:升级软件(cmake)-版本消歧(本地编译)[关闭]

    Closed 这个问题是无关 help closed questions 目前不接受答案 我的机器上安装了 cmake 2 8 0 来自 ubuntu 软件包 二进制文件放置在 usr bin cmake 中 我需要将 cmake 版本至少

随机推荐

  • Android完全自定义控件并且实现监听事件

    本篇文章带来Android的完全自定义控件 载体是自定义一个开关的控件 xff0c 并且能够响应事件 xff0c 首先我们先创一个项目 xff0c 名字就叫ToggleView xff0c 修改MainActivity span class
  • 2016年总结,辛勤劳作的一年

    直到刚才听到门外的爆竹声 才意识到这一年 xff0c 快结束了 今天是11月26号 xff0c 其实离2017年还有一段距离 xff0c 趁着今天有空 xff0c 给自己写一篇文章 其实 xff0c 我是很不想说 xff0c 你好 xff0
  • Android屏幕适配实战

    说一下在项目里面遇到的一个问题 xff0c 和解决思路 需求来源于运营小姐姐 xff0c 她们希望在App的搜索关键字前面加上图片醒目效果图如下 布局很简单左边一个SimpleDraweeView xff0c 右边一个TextView xf
  • 定制阿里代码检查,实现你自己的代码规范检查

    几个月前 xff0c 阿里开源了p3c xff0c 我也接到了老大交给我的技术改造 是这样的 xff0c app是老项目了 xff0c 半年前接入了ARouter xff0c 由于Activity繁多 xff0c 就没有去全局支持ARout
  • Fresco内部诟病引起的初次从网络加载PNG图片失败

    如题描述 xff0c 这个问题在项目中存在已久 xff0c 今天由于自己的功能在首页 xff0c 初次启动的体验极其糟糕 xff0c 所以硬下头皮把这个问题解决了 先来描述一下怎么样一个差的体验吧 就是当我第一次加载网络PNG xff08
  • 不用第三方写一个简单的推流软件

    https github com iOSSinger SGLivingPublisher 不用第三方写一个简单的推流软件 6 commits 1 branch 0 releases 1 contributor Objective C 100
  • 【安防百科】视频监控中常用的分辨率

    http www 360doc com content 17 0317 10 33642774 637585058 shtml 在上一节跟大家谈了摄像机的线数 xff0c 线 是模拟时代的产物 xff0c 当今世界早已是数字化的世界 xff
  • ubuntu20.04下的录屏与视频剪辑软件

    ubuntu20 04下的录屏与视频剪辑 一 录屏软件SimpleScreenRecorder安装与使用1 安装2 设置录制窗口参数3 开始录制 二 视频剪辑软件kdenlive的安装1 安装2 启动 一 录屏软件SimpleScreenR
  • 八、Gazebo 学习笔记:附加网格(Mesh)

    官网教程链接 xff1a http gazebosim org tutorials tut 61 attach meshes 概述 先决条件 xff1a 创建一个移动机器人 网格可以在视觉上和传感器上增加模型的真实感 本教程演示了用户如何使
  • Can I become a good programmer without math and algorithms knowledge?

    Knowledge of algorithms has very little to do with programming skill As some random dude on the internet once said 34 Wh
  • MOXA串口服务器的配置

    1 配置AP 步骤一 xff1a 连接网线 xff0c 如果遇到无法连接本地网络就先查看宽带驱动有没有装好 xff0c 另外换一根网线试试 打开网络连接 点属性打开本地连接属性 步骤二 xff1a 更改电脑的IP地址 xff0c 如192
  • 什么是人工智能?

    Extinguished philosophies lie about the cradle of every science as the strangled snakes beside that of Hercules adapted
  • 【基于Python的ROS学习】

    基于Python的ROS学习 1 订阅topic def span class token function listener span span class token punctuation span span class token
  • P2P中DHT网络介绍

    一 P2P 及 DHT 网络简单介绍 xff1a P2P在思想上可以说是 internet 思想 精神 哲学非常集中的体现 xff0c 共同的参与 xff0c 透明的开放 xff0c 平等的分享 xff08 让我想起之前学习过的 xff0c
  • C++ 库

    基础类 1 Dinkumware C 43 43 Library 参考站点 xff1a http www dinkumware com P J Plauger编写的高品质的标准库 P J Plauger博士是Dr Dobb 39 s程序设计
  • APM(PX4-v2) 定高模式相关(AltHold)

    1 分析log文件 xff0c 及其消息的赋值 LOG CONTROL TUNING MSG sizeof log Control Tuning 34 CTUN 34 34 Qhhfffecchh 34 34 TimeUS ThrIn An
  • APM的解锁(ARM)流程

    解锁检测函数 解锁检测函数是arm motors check xff08 xff09 xff0c 作为scheduler每秒运行10此 xff0c 定义在motors cpp中 xff0c 定义如下 define ARM DELAY 20
  • 智能运维就是 由 AI 代替运维人员?

    本文整理自 GOPS2017 上海站演讲 从说到做 大型企业智能运维的360度解析 讲师简介 孙杰 xff0c 国内一线运维专家 xff0c 从业十几载的IT老兵 xff0c 专注于系统 运维 云计算和数据中心管理 xff0c 先后在外企
  • AIOps 风向标!GOPS2018深圳站实录(附白皮书及PPT)

    本文相关下载资料 xff1a 本次大会精彩演讲 PPT 企业级 AIOps 实施建议 白皮书 DevOps 标准体系及能力成熟度模型 盼星星盼月亮 xff0c 2018 GOPS 深圳站终于到来了 xff01 hia hia hia hia
  • Linux UART接口调试技巧

    在嵌入式项目中 xff0c UART接口的使用频率很高 xff0c 多种模块 2G通信模组 蓝牙模块 xff0c 等等 都会通过UART接口与主控MCU相连 本文将梳理UART接口调试流程 xff0c 为调试工作提供参考 xff0c 解决调