内核空间中的RS232串口通信

时间:2013-09-30 14:55:17

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

我正在为 Linux v3.2 编写一个内核模块来控制外部激光器,但是我在通过 RS232串口上传输信号时遇到了问题。机。

似乎已经在我的内核中编译了一个串行驱动程序,该驱动程序拥有我想要访问的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 串行驱动程序并将其替换为我自己的自定义RS232驱动程序,但我不想在这里重新发明轮子 - 默认Linux serial 驱动程序似乎支持我需要的功能。

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

1 个答案:

答案 0 :(得分:4)

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

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