如何从内核模块打开/写入/读取uart设备?

时间:2018-06-26 14:41:13

标签: c linux module kernel uart

设备是扫描仪。我知道uart5是在dtsi文件中设置的,并且在用户空间中它在/ dev / ttymxc4下列出。从用户空间,我知道我可以通过

fd = open("/dev/ttymxc5", O_RDWR|O_NOCTTY|O_NONBLOCK);
if (fd < 0)
{
    fprintf (stderr,"Open error on %s: %s\n", SCANNER_UART, strerror(errno));
    return nullptr;
}

然后使用termios设置所有设置,例如波特率,使用write调用等写入数据。

我想在sysfs下抽象很多命令。我已经这样设置了“ uart驱动程序”:

result = uart_register_driver(&scanner_reg);
if (result)
    return result;

result = uart_add_one_port(&scanner_reg, &scanner_port);
if (result)
    uart_unregister_driver(&scanner_reg);

我正在使用gpio线打开系统和其他一些东西。但是,在原理图中,我看不到这些东西的gpio线。

UART5_CTS_HOST_SCAN_3_3V
UART5_RTS_HOST_SCAN_3_3V
UART5_RxD_HOST_SCAN_3_3V
UART5_TxD_HOST_SCAN_3_3V

我只是不确定如何从设备打开/写入/读取数据。我知道关于sys_open和类似的调用,但是我知道它们不是执行此操作的“正确”方法;我不想遍历用户空间。

所以,总而言之,我该怎么办

  1. 在模块和“ / li”中“选择” / dev / ttymxc4设备
  2. 打开,设置波特率以及向设备读取/写入数据?

谢谢!请帮忙!对于uart来说,它是新事物,我过去曾经处理过i2c,而且看起来似乎不太复杂。

1 个答案:

答案 0 :(得分:0)

这就是我所做的。我从内核而不是任何内核本机方法访问uart文件。这是作弊,但有效。所以,

#define SCANNER_UART "/dev/ttymxc4"
...
static int scanner_open(struct inode *inode, struct file *file)
    struct termios term;
...
    scanner_file = filp_open(SCANNER_UART, O_RDWR|O_NOCTTY|O_NONBLOCK, 0);
...
    if (serial_tty_ioctl(scanner_file, TCGETS, (unsigned long)&term) < 0)
    {
        pr_err("%s: Failed to get termios\n", __FUNCTION__);
        return -1;
    }

    term.c_cflag  = B9600 | CLOCAL | CREAD; // 115200 if change, must configure scanner

    /* No parity (8N1) */
    term.c_cflag &= ~PARENB;
    term.c_cflag &= ~CSTOPB;
    term.c_cflag &= ~CSIZE;
    term.c_cflag |= CS8;

    term.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
    term.c_oflag &= ~OPOST;

    term.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON);

    term.c_cc[VTIME] = 5; // 0.5 seconds read timeout
    term.c_cc[VMIN] = 0;  // read does not block

    if (serial_tty_ioctl(scanner_file, TCSETS, (unsigned long)&term) < 0)
    {
        pr_err("%s: Failed to set termios\n", __FUNCTION__);
        return -1;
    }
...
static const struct file_operations scanner_fops = {
    .owner          = THIS_MODULE,
    .write          = scanner_write,
    .read           = scanner_read,
    .open           = scanner_open,
    .release        = scanner_close,
    .llseek         = no_llseek,
};

struct miscdevice scanner_device = {
    .minor = MISC_DYNAMIC_MINOR,
    .name = "scanner",
    .fops = &scanner_fops,
};

...
    ret = misc_register(&scanner_device);
    if (ret) {
        pr_err("can't misc_register :(\n");
        return ret;
    }

然后,我使用Sysfs向用户提供功能。这是正确的方法吗?可能不是,但这是出于我的目的。它实际上是在将用户空间的实现方式转移到内核。