嵌入式Linux:SC16IS752缓冲区溢出

嵌入式Linux:SC16IS752缓冲区溢出,linux,Linux,在我的系统中,我使用I2C到2xUART转换器SC16IS752。Linux内核源代码已经为该芯片提供了驱动程序,但仅限于SPI模式。现在,我正在尝试修改这个驱动程序,以便进行I2C工作。I2C的速度为400 kHz。该转换器的UART连接设备的波特率为38400。该设备每1s发送包含约100字节数据的数据包。SC16IS752有64字节的RX FIFO,因此每个数据包必须处理两次 我面临着长时间延迟的问题。当FIFO达到阈值时,硬件中断发生,现在执行IRQ处理程序: static irqret

在我的系统中,我使用I2C到2xUART转换器SC16IS752。Linux内核源代码已经为该芯片提供了驱动程序,但仅限于SPI模式。现在,我正在尝试修改这个驱动程序,以便进行I2C工作。I2C的速度为400 kHz。该转换器的UART连接设备的波特率为38400。该设备每1s发送包含约100字节数据的数据包。SC16IS752有64字节的RX FIFO,因此每个数据包必须处理两次

我面临着长时间延迟的问题。当FIFO达到阈值时,硬件中断发生,现在执行IRQ处理程序:

static irqreturn_t sc16is7x2_irq(int irq, void *data)
{
    struct sc16is7x2_channel *chan = data;

#ifdef DEBUG
    /* Indicate irq */
    chan->handle_irq = true;
#endif

    /* Trigger work thread */
    sc16is7x2_dowork(chan);
    return IRQ_HANDLED;
}

static void sc16is7x2_dowork(struct sc16is7x2_channel *chan)
{
    printk("sc16is7x2_dowork \n");

    if(!freezing(current))
    {
        queue_work(chan->workqueue, &chan->work);
    }
}
因此,如您所见,中断处理程序将来自SC16IS752 FIFO的处理数据的工作放入队列中

在这里,我面临着一个问题。sc16is7x2_irq函数在中断发生后立即执行。但排队工作是在中断发生后25毫秒内执行的。但在此之后,FIFO溢出,数据丢失100字节,在26毫秒内传输


在这种情况下,正确的解决方案是什么?如何在Linux内核中减少25毫秒的延迟?

我确定了延迟的来源,它们是由调用printk函数引起的。其中一个功能的执行时间约为2-3毫秒。

如果不在系统上进行评测,很难准确判断这25毫秒的来源。上下文切换确实需要一些时间,但25毫秒看起来太长了;可能正在运行优先级更高的进程es。设置更高的优先级可能会有所帮助,不过我个人只需要创建第二个缓冲区,irq就可以使用它来存储数据并将数据指针传递给您的进程。我尝试过使用优先级和scheldule策略,但它也没有给出期望的结果。我尝试将实用程序nice用于优先级管理,将chrt用于select scheldule策略。策略SCHED_FF和SCHED_RR也没有给出期望的结果。优先级无论如何都不会完全解决您的问题,因为在您的IRQ和流程之间总是有机会出现另一个不相关的IRQ。当然,这是1/1000000的机会,但这样的问题确实会发生,而且很难抓住和解决。取决于您的硬件,DMA在这方面也可能有所帮助,因为它不使用CPU来传输数据。