从 Linux 用户空间设置 16550A UART 硬件 FIFO 中断级别

Posted

技术标签:

【中文标题】从 Linux 用户空间设置 16550A UART 硬件 FIFO 中断级别【英文标题】:Set 16550A UART Hardware FIFO interrupt level from Linux Userspace 【发布时间】:2016-12-07 07:38:27 【问题描述】:

我目前正在使用兼容 16550 的 UART,并且我希望能够更改 FIFO 中断触发级别(我在高 UART 负载下丢弃字节并且我想降低阈值 - 这是一个功率不足的嵌入式系统)。当然,如果我愿意,我可以在 8250_port.c 驱动程序中更改它:

[PORT_NS16550A] = 
    .name       = "NS16550A",
    .fifo_size  = 16,
    .tx_loadsz  = 16,
    .fcr        = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
    .flags      = UART_CAP_FIFO | UART_NATSEMI,
,

但是从用户空间更改它会方便得多,而无需重新编译内核。

我希望following documentation 已过时:

截至 2000 年底,Linux 用户无法设置这些 直接(setserial 做不到)。虽然许多 PC 只有 16550 使用 16 字节缓冲区,更好的 UART 具有更大的缓冲区。

如果有办法这样做(例如一些新的 ioctl),那么 seterial (8) 和 stty (1) 还没有公开接口。

【问题讨论】:

哦,还有 isaset -y -f 0x3fA 0x07(直接戳/dev/ttyS0的FCR寄存器)不算! 如果isaset不算数,为什么其他解决方案也算数? 因为无论何时重新打开端口,更改都会丢失。此外,它必须由特权用户来完成 - 从用户空间中插入随机 IO 端口通常不是一个安全的选择! 有一个 sysfs 方法必须严格以 root 身份运行:echo 4 > /sys/class/tty/ttyS6/rx_trig_bytes。 isaset 更安全,但不是可以委派特权的东西。 2014 年是added to the kernel。 【参考方案1】:

我认为这个问题的一般解决方案是使用 setserial 来使 uart 改变模式。例如,使用 pericom PI7C9X7958,您有多种操作模式,例如“550”和 950 模式。这些对应于 16550 或 16950 标准 uart 类型。每种模式都有与其相关的特定 fifo 大小和一些其他功能。

所以,如果你的设备支持,你可以试试

setserial -v /dev/ttyS1 uart 16950

然后去验证

setserial -g /dev/ttyS1 /dev/ttyS1,UART:16950/954,端口:0xc800,IRQ:16

【讨论】:

我不想改变 UART 类型;我正在尝试更改 FIFO 阈值级别,即原始帖子中的“UART_FCR_R_TRIG_10”标志。

以上是关于从 Linux 用户空间设置 16550A UART 硬件 FIFO 中断级别的主要内容,如果未能解决你的问题,请参考以下文章

如何在linux上使用串口设备

Linux 下FTP空间大小能设置吗?

linux signal

LInux环境安装flasher插件

linux2.4内核调度

如何从 Linux 中的用户空间访问物理地址?