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

标签 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 设置所有设置,如波特率、使用写入调用写入数据等。

我想抽象出 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. “选择”我的模块中的/dev/ttymxc4 设备
  2. 打开设备,设置波特率,读/写数据到设备?

谢谢!请帮忙!对于所有 uart 都是新手,我过去处理过 i2c,它似乎不那么复杂。

最佳答案

这就是我所做的。我正在从内核访问 uart 文件,而不是使用任何内核 native 方法。这是作弊,但它有效。所以,

#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 为用户提供功能。这是正确的方法吗?可能不是,但它正在为我的目的工作。它实质上是将用户空间的实现方式转移到内核。

关于c - 如何从内核模块打开/写入/读取 uart 设备?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51045615/

相关文章:

c++ - 为什么会有单独的 "trie_node"和 "trie"结构?

regex - 考虑到特殊的正则表达式,如何正确使用 sed 替换命令的反向引用

R shiny - Shiny 模块函数中最后单击的按钮 id

c - 如何在函数文件和项目文件中正确包含自己的库

c - 使用另一个访问重新打开文件描述符?

C 库编译错误

linux - apt-get 如何比较两个不同版本方案

linux - 如何在 bash 中创建一个附加到另一个文件的伪文件

ASP.NET 处理程序未在 IIS7 上运行

javascript - Grunt 任务自动为新模块生成文件