“中断方式”来读取串口

在 VxWorks 中,一个已经实例化(attach 完成)的串口驱动,应用层如何利用"中断方式"来读取串口发来的数据?


🔥 一、关键点:应用层不直接注册中断

很重要的一句话:

VxWorks 中,串口的中断处理由驱动(NS16550、Zynq UART、PPC DUART 等)内部完成,应用层无法直接中断绑定。

应用层只能看到一个设备文件:

复制代码
/tyCo/0
/tyCo/1
/duart/0
/ttyS0
...

以及接口:

c 复制代码
open()
read()
write()
ioctl()

🔥 二、驱动内部是如何处理接收中断的?

所有 VxWorks 的串口驱动都采用同样机制:

1. 中断到来时

UART → 触发 RX interrupt → CPU

2. 驱动 ISR(uartIsr()) 会做的事情:

  • 读取 UART 数据寄存器
  • 把收到的字节写入 环形缓冲区(ring buffer)
  • 唤醒等待的任务(如果 read() 阻塞)
  • 或者触发 TTY 驱动回调

⚠ 应用层无法直接执行 ISR

⚠ ISR 只存在于驱动内部


🔥 三、应用层如何"使用中断方式"接收数据?

中断方式不是由你注册。

中断方式 = 你调用 read() 时阻塞,驱动内部 ISR 填充数据并唤醒你。

VxWorks 提供三种读取方式:


✔ 方式 1:阻塞 read(最常见)

当串口收到数据,中断将数据放入驱动 ring buffer,并唤醒 read。

c 复制代码
int fd = open("/tyCo/0", O_RDONLY, 0);

char buf[64];
int n;

while (1)
{
    n = read(fd, buf, sizeof(buf));  // 中断到来后才返回
    if (n > 0)
        printf("recv: %.*s\n", n, buf);
}

特点:

  • CPU 不需要轮询
  • 中断到来 ISR → 数据入队 → read() 被唤醒

这是 纯中断驱动 的收数据方式。


✔ 方式 2:select() + read()(异步事件等待)

更专业的写法,用事件等待,不阻塞 CPU:

c 复制代码
int fd = open("/tyCo/0", O_RDWR, 0);

fd_set readFds;
char buf[128];

while (1)
{
    FD_ZERO(&readFds);
    FD_SET(fd, &readFds);

    select(fd+1, &readFds, NULL, NULL, NULL);  // 中断填入数据后返回

    if (FD_ISSET(fd, &readFds))
    {
        int n = read(fd, buf, sizeof(buf));
        printf("recv: %.*s\n", n, buf);
    }
}

这也是中断驱动,因为 select() 的唤醒来自中断处理。


✔ 方式 3:使用 TTY 模式(回调方式)

对于 /tyCo/x,串口被连接到 TTY 层

TTY 层本身支持:

  • 行模式
  • 信号控制
  • 流量控制

实际上 TTY 也是以 中断接收 + 内部 FIFO 方式实现。

你可以使用:

c 复制代码
ioctl(fd, FIOASYNC, TRUE);
ioctl(fd, FIOSETOWN, (int)taskIdSelf());

然后在 signal handler 处理数据(高级用法)。


🔥 四、真正注册中断的位置在哪?(不是应用层)

中断是驱动在 attach 阶段做的:

例如:

c 复制代码
vxbIntConnect(pInst, 0, uartIsr, pDrvCtrl);
vxbIntEnable(pInst, 0);

或 BSP 老 API:

c 复制代码
intConnect(INUM_TO_IVEC(intNum), uartIsr, pDrvCtrl);
intEnable(intNum);

ISR → TTY input routine → ring buffer → read()

应用程序 无需直接操作中断。


🔥 五、如果你自己写驱动,如何在驱动里处理中断?(附结构)

驱动内部典型流程:

c 复制代码
LOCAL void uartIsr(void *pArg)
{
    UART_DEV *pDrvCtrl = pArg;

    while (UART_RX_READY())
    {
        char c = UART_READ_CHAR();
        ringPut(&pDrvCtrl->rxRing, c);
    }

    /* 唤醒 read() 任务 */
    selWakeupAll(&pDrvCtrl->selList);
}

应用层只需:

c 复制代码
select()
read()

📌 总结

❗ 应用层不能注册串口中断

✔ 串口驱动内部自动处理中断(ISR → ring buffer)

✔ 你在应用层使用 read()/select() 就是在"利用中断"

✔ 中断处理函数由驱动 attach 阶段注册


相关推荐
M78佐菲33 分钟前
ARM学习笔记(12)
linux·arm开发·笔记·嵌入式硬件·学习
CHENKONG_CK37 分钟前
RFID 赋能汽车零部件涂装产线,构建全流程数字化追溯体系
网络·人工智能·单片机·网络协议·tcp/ip·汽车
璞致电子1 小时前
基于 AD9361 (PZSDR‑P201Pro) 软件无线电实战综述:从板卡选型、硬件平台升级到 GNU Radio QPSK 完整收发链路
经验分享·嵌入式硬件·fpga开发·软件无线电·sdr·璞致电子
高斯的手稿08012 小时前
CS+中,全局变量的正确管理方式
嵌入式硬件
俊基科技2 小时前
喇叭 95dB、麦克风贴到 1cm,回音还能消干净?拆解 A-29P 的消回音设计
嵌入式硬件·硬件开发·ai降噪·回音消除·拾音降噪
2401_862880822 小时前
LCD 显示与触控屏驱动开发
驱动开发·嵌入式硬件
糖糖单片机设计3 小时前
基于STM32的指纹刷卡智能门禁系统设计(RC522 + AS608 + 蓝牙远程开锁 + 断电记忆)
人工智能·stm32·嵌入式硬件·51单片机·语音识别
HRTOS4 小时前
HRTOS Shell继续完善:优化printf缓冲区与字符串越界保护,国庆后随新版本更新
运维·单片机·嵌入式硬件·算法·51单片机
YYRAN_ZZU4 小时前
GMSL开发加解串配置介绍
linux·嵌入式硬件
zhaoshuzhaoshu4 小时前
回调函数详解 —— 以 STM32 平台为例
嵌入式硬件