【问题标题】:RS232 serial port communication in kernelspace内核空间中的 RS232 串口通信
【发布时间】:2013-09-30 14:55:17
【问题描述】:

我正在为 Linux v3.2 编写一个内核模块来控制外部激光器,但是我无法通过 RS232 串行端口 上的机器。

似乎已经在我的内核中编译了一个serial驱动程序,持有我要访问的 ioport 地址的所有权:

# cat /proc/ioports | grep serial
  02e8-02ef : serial
  02f8-02ff : serial
  03f8-03ff : serial

这是有道理的,因为 Linux 允许用户空间程序使用/dev/ttyS* 设备节点通过串行端口进行通信。例如,以下是我为 LCD 面板设置设备的方法:

#include <fcntl.h>
#include <termios.h>
#include <unistd.h>

...

    /* Initialization and configuration */
    const char *const lcd_dev = "/dev/ttyS1";        
    int lcd_dev_fd = open(lcd_dev, O_RDWR | O_NOCTTY | O_NDELAY);
    fcntl(lcd_dev_fd, F_SETFL, 0);

    struct termios options;
    tcgetattr(lcd_dev_fd, &options);

    cfsetispeed(&options, B19200);
    cfsetospeed(&options, B19200);
    options.c_cflag |= (CLOCAL | CREAD);
    options.c_cflag &= ~PARENB;
    options.c_cflag &= ~CSTOPB;
    options.c_cflag &= ~CSIZE;
    options.c_cflag |= CS8;
    options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
    options.c_iflag &= ~(IXON | IXOFF | IXANY);
    options.c_oflag &= ~OPOST;

    tcsetattr(lcd_dev_fd, TCSANOW, &options);

    ...

    /* sending bytes */
    const unsigned char scls[] = {0xFE, 'X', 0xFE, 75, 0xFE, 84, 0xFE, 'H'};
    write(lcd_dev_fd, scls, sizeof(scls);

但是,这是一个用户空间接口,因此与我的内核空间模块不兼容。我需要一种在内核空间内产生相同效果的方法(RS232 串行 I/O)。

虽然我可以卸载默认的 Linux serial 驱动程序并用我自己的自定义 RS232 驱动程序替换它,但我不想在这里重新发明轮子——默认的 Linux serial strong> 驱动似乎支持我需要的功能。

有没有一种简单的方法通过内核空间中的 RS232 串行端口进行通信(可能通过这个默认的 Linux serial 驱动程序),还是我只需要编写自己的自定义 RS232 驱动程序?

【问题讨论】:

  • 为什么不能在用户空间中编写所有应用程序?为什么需要设备驱动程序?
  • 我认为这个链接可以让你对Linux内核串行驱动架构有一个很好的了解:free-electrons.com/doc/serial-drivers.pdf
  • @eepp 驱动程序通过几个 ioport 地址控制激光器,并执行非常硬件特定的操作。串行 I/O 必须出现在各个代码段中,整个代码将与串行 I/O 非常交织。换句话说,现有的代码和设计不适合用户空间。
  • @VilhelmGray - eepp 关于移动到用户空间的想法是有效的,但如果你觉得你不能,你可能想看看内核中确实使用串行端口的东西,例如串行控制台,KGDB等等。作为务实的事情,访问特定的串行硬件并没有那么复杂,所以如果你不能使用现有的抽象找到一个优雅的解决方案,复制实际的UART接口代码可能不是结束只要您设想的硬件范围很小,就可以成为世界第一。
  • 最小化内核内容确实是个好主意。制作一个微型驱动程序,通过ioctl() 公开您的 ioport 操作,然后其余的可以存在于用户空间中。

标签: linux-kernel serial-port linux-device-driver


【解决方案1】:

看看行学科。您可以使用它将 tty 设备附加到内核空间中定义的一些读写例程,从而使用串行线编写驱动程序。线路规程从用户空间附加到它,内核将完成所有其余的工作。

一个很好的例子是 slcan (drivers/net/can/slcan.c)。可以在 can-utils (https://gitorious.org/linux-can/can-utils) 中找到处理此问题的 libc 调用示例。如果您更喜欢按照 Linux 设备驱动程序的第 18 章工作,这将是一个很好的第一步:http://www.makelinux.net/ldd3/chp-18,尽管这本书不是最新的。一些细节也可以在http://www.linusakesson.net/programming/tty/找到。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-11-15
    • 2011-03-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多