Linux 下串口调试的全过程及源代码 (linux 串口调试 源代码)

串口调试是开发人员在硬件调试中经常遇到的问题之一。在 Linux 环境下,串口调试也是一项复杂的任务。本文将介绍在 Linux 环境下串口调试的全过程,并提供源代码以供参考。

1. 准备工作

在进行串口调试之前,需要先准备一些工具和设备。需要一台 Linux 机器以及一个串口转 USB 线缆。需要安装一些必要的软件,如 minicom 等。需要连接串口转 USB 线缆到要调试的硬件设备上。

2. 配置串口

在 Linux 环境下,串口配置分为两部分:内核配置和用户空间配置。内核配置主要是针对硬件的,而用户空间配置则是针对软件的。

2.1 内核配置

在进行内核配置之前,需要确定 CPU 架构。在我们的例子中,我们使用的是 x86 架构。接着,我们需要在内核配置文件中添加以下配置:

“`c

CONFIG_SERIAL_8250=y

CONFIG_SERIAL_8250_CONSOLE=y

CONFIG_SERIAL_8250_NR_UARTS=4

CONFIG_SERIAL_8250_RUNTIME_UARTS=1

CONFIG_SERIAL_CORE=y

CONFIG_SERIAL_CORE_CONSOLE=y

CONFIG_SERIAL_UARTLITE=y

CONFIG_SERIAL_CORE_IRQ=y

CONFIG_SERIAL_CORE_AMBA_PL011=y

“`

以上配置表示启用串口驱动,并开启控制台。其中,`CONFIG_SERIAL_8250_NR_UARTS` 表示更大串口数量,`CONFIG_SERIAL_8250_RUNTIME_UARTS` 表示当前使用的串口数量。`CONFIG_SERIAL_CORE_AMBA_PL011` 表示使用 PL011 串口控制器,这个需要根据硬件具体情况进行调整。

2.2 用户空间配置

在用户空间中,我们需要配置 minicom。在安装 minicom 后,我们需要对其进行配置。可以通过以下命令进行配置:

“`bash

sudo minicom -s

“`

通过此命令,我们可以设置串口波特率、数据位、奇偶校验位等参数。配置完成后,我们就可以使用 minicom 进行串口调试了。

3. 编写串口调试程序

在实际开发中,我们经常需要编写一些简单的串口调试程序。下面是一个串口输出 “Hello, world!” 的例子:

“`c

#include

#include

#include

int mn()

{

int fd;

struct termios options;

char buf[] = “Hello, world!\n”;

fd = open(“/dev/ttyUSB0”, O_RDWR | O_NOCTTY | O_NDELAY);

if (fd

{

perror(“open”);

return -1;

}

fcntl(fd, F_SETFL, 0);

tcgetattr(fd, &options);

cfsetispeed(&options, B9600);

cfsetospeed(&options, B9600);

options.c_cflag |= (CLOCAL | CREAD);

options.c_cflag &= ~CSIZE;

options.c_cflag |= CS8;

options.c_cflag &= ~PARENB;

options.c_iflag &= ~INPCK;

options.c_cflag &= ~CSTOPB;

options.c_cc[VTIME] = 0;

options.c_cc[VMIN] = 1;

tcsetattr(fd, TCSANOW, &options);

write(fd, buf, sizeof(buf));

close(fd);

return 0;

}

“`

以上代码首先打开串口 `/dev/ttyUSB0`,之后通过 `tcsetattr()` 函数进行串口配置,如设置波特率、数据位、奇偶校验等。使用 `write()` 函数输出 “Hello, world!”。

4.

相关问题拓展阅读:

linux 怎么 在 驱动中 使用串口

Linux发行版自带u to serial驱动,以模块方式编译驱动,在内核源握碰棚代码目录下运段则行Make MenuConfig选择Devces

drivers–>USB seupport–> USB Serial Converter support

–> USB driver for G and CDMA modems & USB Generic

Serial Driver,保存退出。运行make

linux kernel 没有输出信息 怎么调试

内核中的bug也是多种多样的。它们的产生有无数的原唤运因,同时表象也变化多端。从隐藏在源代码中的错误到展现在目击者面前的bug,其发作往往是猜简一系列和兆梁连锁反应的事件才可能出发的。虽然内核调试有一定的困难,但是通过你的努力和理解,说不定你会喜欢上这样的挑战。

最近工作在调试u虚拟串口,让其作为kernel启动的调试串口老埋,以及user空间的输入输出控制台。

利用这个机会,学习下printk如何选择往哪个console输出以及user空间下控制台如何选择,记录与此,与大家共享,也尺含绝方便自己以后翻阅。

Kernel版本号:3.4.55

依照我的思路(还是时间顺序)分了4部分,指定kernel调试console , kernel下printk console的选择 ,kernel下console的注册,user空间console的选陵姿择。

一 指定kernel调试console

首先看kernel启动时如何获取和处理指定的console参数。

kernel的启动参数cmdline可以指定调试console,如指定‘console=ttyS0,115200’,

kernel如何解析cmdline,我之前写了一篇博文如下:

根据之前的分析,cmdline中有console=,start_kernel中parse_args遍历.init.setup段所有obs_kernel_param。

kernel/printk.c中注册了‘console=’的解析函数console_setup(注册了obs_kernel_param),所以匹配成功,会调用console_setup来解析,如下:

view plain copy

static int __init console_setup(char *str)

{

char buf.name) + 4>; /* 4 for index */

char *s, *options, *brl_options = NULL;

int idx;

#ifdef CONFIG_A11Y_BRAILLE_CONSOLE

if (!memcmp(str, “brl,”, 4)) {

brl_options = “”;

str += 4;

} else if (!memcmp(str, “brl=”, 4)) {

brl_options = str + 4;

str = strchr(brl_options, ‘,’);

if (!str) {

printk(KERN_ERR “need port name after brl=\n”);

return 1;

}

*(str++) = 0;

}

#endif

/*

* Decode str into name, index, options.

*/

if (str >= ‘0’ && str = ‘0’ && *s name, name, sizeof(c->name));

c->options = options;

#ifdef CONFIG_A11Y_BRAILLE_CONSOLE

c->brl_options = brl_options;

#endif

c->index = idx;

return 0;

}

kernel利用结构体数组console_cmdline,最多可支持8个cmdline传入的console参数。

__add_preferred_console将name idx options保存到数组下一个成员console_cmdline结构体中,如果数组中已有重名,则不添加,并置selected_console为最新添加的console_cmdline的下标号。

比如cmdline中有“console=ttyS0,console=ttyS1,9600”

则在console_cmdline数组中console_cmdline代表ttyS0,console_cmdline代表ttyS1,而selected_console=1.

二 kernel下printk console的选择

kernel下调试信息是通过printk输出,如果要kernel正常打印,则需要搞明白printk怎么选择输出的设备。

关于printk的实现原理,我在刚工作的时候写过一篇博文,kernel版本是2.6.21的,但是原理还是一致的,可供参考:

printk首先将输出内容添加到一个kernel缓冲区中,叫log_buf,log_buf相关代码如下:

view plain copy

#define MAX_CMDLINECONSOLES 8

static struct console_cmdline console_cmdline;

static int selected_console = -1;

static int preferred_console = -1;

int console_set_on_cmdline;

EXPORT_SYMBOL(console_set_on_cmdline);

/* Flag: console code may call schedule() */

static int console_may_schedule;

#ifdef CONFIG_PRINTK

static char __log_buf;

static char *log_buf = __log_buf;

static int log_buf_len = __LOG_BUF_LEN;

static unsigned logged_chars; /* Number of chars produced since last read+clear operation */

static int saved_console_loglevel = -1;

log_buf的大小由kernel menuconfig配置,我配置的CONFIG_LOG_BUF_SHIFT为17,则log_buf为128k。

printk内容会一直存在log_buf中,log_buf满了之后则会从头在开始存,覆盖掉原来的数据。

根据printk的实现原理,printk最后调用console_unlock实现log_buf数据刷出到指定设备。

这里先不关心printk如何处理log buf数据(比如添加内容级别),只关心printk如何一步步找到指定的输出设备,根据printk.c代码,可以找到如下线索。

printk->vprintk->console_unlock->call_console_drivers->_call_console_drivers->_call_console_drivers->__call_console_drivers

看线索更底层__call_console_drivers代码。如下:

view plain copy

/*

* Call the console drivers on a range of log_buf

*/

static void __call_console_drivers(unsigned start, unsigned end)

{

struct console *con;

for_each_console(con) {

if (exclusive_console && con != exclusive_console)

continue;

if ((con->flags & CON_ENABLED) && con->write &&

(cpu_online(p_processor_id()) ||

(con->flags & CON_ANYTIME)))

con->write(con, &LOG_BUF(start), end – start);

}

}

for_each_console定义如下:

view plain copy

/*

* for_each_console() allows you to iterate on each console

*/

#define for_each_console(con) \

for (con = console_drivers; con != NULL; con = con->next)

遍历console_drivers链表所有console struct,如果有exclusive_console,则调用与exclusive_console一致console的write,

如果exclusive_console为NULL,则调用所有ENABLE的console的write方法将log buf中start到end的内容发出。

可以看出,execlusive_console来指定printk输出唯一console,如果未指定,则向所有enable的console写。

默认情况下execlusive_console=NULL,所以printk默认是向所有enable的console写!

只有一种情况是指定execlusive_console,就是在console注册时,下面会讲到。

到这里就很明了了,kernel下每次printk打印,首先存log_buf,然后遍历console_drivers,找到合适console(execlusive_console或所有enable的),刷出log。

哪里有LINUX下的串口调试工具

minicom

minicom 是一款启动速度快,功能强大的串口终端调试工具,当然缺点就是纯字符界面,没有图形界面的调试工具看起来直观方便,但是它功能十分强大,并且在一些没有屏幕的嵌入式主板上运行颇有用处。下面给出具体的安装与使用教程:

安装:apt-get install minicom

使用流程:

安装完毕后通过命令 “minicom” 运行软件,首页已经给了使用说明,Minicom 使用经常遇到三个键的组合操作,如 “CTRL-A Z”,这表示先同时按下 CTRL 和 “A”(不区分大写),然后松开此二键再按下 “Z”。按照此方法,打开帮助说明:

可以看到有很多功能,这里只进行初步演示坦梁,按下 “O” 进入配置页,如下:

选择 “Serial port setup” 选项,然后按回车进入串口设置页,如下:

根据我们系统中的实际串口设备名更改成以下设置,如下图所示:

设置好以后知信春返回到上一级,选择 “Save setup as dfl” 进行保存即可,然后 Exit。确保串口设备已经接入后,重新运行 minicom 软件,就可以进行串口数据的收发了,如果没有发现设置的串口设备 minicom 运行会提示出错,如下所示:

如果需要修改设置,那么需要运行 “minicom -s” 重新进行设置。搭耐在配置正确的情况下,连接我的 Openwrt 开发板进行通讯演示:

关于linux 串口调试 源代码的介绍到此就结束了,不知道你从中找到你需要的信息了吗 ?如果你还想了解更多这方面的信息,记得收藏关注本站。


数据运维技术 » Linux 下串口调试的全过程及源代码 (linux 串口调试 源代码)