首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >ARM A7 Linux原始中断处理可能吗?

ARM A7 Linux原始中断处理可能吗?
EN

Stack Overflow用户
提问于 2016-08-13 07:12:51
回答 2查看 522关注 0票数 1

我想写一个在Linux下控制步进电机的开源核心驱动程序。在这种情况下,尤其是对于3D打印机。

其基本思想是,驱动程序在一个IO端口上保留引脚,然后一次操作这些引脚。它接收一个充满“切换这个,切换那个”值的缓冲区,然后使用硬件计时器将这些值发送到端口。

现在的问题是:有没有办法尽可能快地处理特定的硬件中断?

有问题的芯片是Allwinner H3,我使用的是该芯片的TMR1资源(IRQ51)。我可以很好地使用它,它也可以作为中断工作:

代码语言:javascript
复制
static irqreturn_t stepCore_timer_interrupt(int irq, void *dev_id)
{
        writel(TMR1_IRQ_PEND, TMR_IRQ_ST_VREG);
        icnt++;

        porta_state = readl(PA_VDAT);
        porta_state &= porta_mask;

        if(icnt & 0x00000001)
        {
            porta_state |= 0x00000001;
        }

        writel(porta_state, PA_VDAT);

        return IRQ_HANDLED;
}

static struct irqaction stepCore_timer_irq = {
        .name = "stepCore_timer",
        .flags = IRQF_DISABLED | IRQF_NOBALANCING , IRQF_PERCPU,
        .handler = stepCore_timer_interrupt,
        .dev_id = NULL,
};

static void stepCore_timer_interrupt_setup(void)
{
    int ret;
    u32 val;

    writel( 24000000, TMR1_INTV_VALUE_VREG );
    writel( ( TMR1_MODE_CONTINUOUS | TMR1_CLK_PRES_1 | TMR1_CLK_SRC_OSC24M ), TMR1_CTRL_VREG );

    ret = setup_irq(SUNXI_IRQ_TIMER1, &stepCore_timer_irq);
    if (ret)
            printk("%s: ERROR: failed to install irq %d\n", __func__, SUNXI_IRQ_TIMER1);
    else
            printk("%s: irq %d installed\n", __func__, SUNXI_IRQ_TIMER1);

    ret = irq_set_affinity_hint(SUNXI_IRQ_TIMER1, cpumask_of(3));
    if (ret)
            printk("%s: ERROR: failed to set irq affinity for irq %d\n", __func__, SUNXI_IRQ_TIMER1);
    else
            printk("%s: set irq affinity for irq %d\n", __func__, SUNXI_IRQ_TIMER1);
    /* Enable timer0 interrupt */
    val = readl(TMR_IRQ_EN_VREG);
    writel(val | TMR1_IRQ_EN, TMR_IRQ_EN_VREG);

}

TMR1在其他方面都没有使用过(实际上,我必须自己添加它),并且到目前为止都可以正常工作。然而,在处理相当简单的IRQ例程时有相当多的延迟。因为我想生成一些可用于3D打印机的代码,所以我非常喜欢一个更“稳定”的定时器中断。

所以,我的问题是:有没有办法在Linux中有一个非常短的IRQ例程,并且具有尽可能高的优先级?或者根本不关心Linux调度器,而只是“它是什么吗”?基本上是一个原始的IRQ处理程序,忽略了Linux认为它应该是什么?

不管怎么说,它运行的内核就是专门用来完成这个任务的。处理程序将尽可能简短:从数组中获取u32,将其写入端口,完成。

最好,我希望有一些东西,只是忽略了Linux的其余部分。是的,我知道这不是做这件事的方法。但这是为一个相当特殊的情况而设计的,所以我毫不犹豫地调整常规的内核源代码以满足这些需求。

哦,这提醒了我,内核是3.4.112,带有合适的preempt-rt补丁。

任何帮助都是非常感谢的。

大家好,

克里斯

EN

回答 2

Stack Overflow用户

发布于 2016-08-13 13:38:19

以下是此问题的一般解决方案。您可以编写一个内核模块,它将覆盖现有的中断处理例程,并将替换为您自己的例程,您可以在其中处理您感兴趣的irq,并将所有irq重定向到现有的内核中断处理例程。对于CPU,您可以通过获取低级x86指令来获取现有的中断描述例程(lidt)地址。我相信这对ARM来说也是可能的。现在,Linux有CPU隔离isolcpus的技术。通过利用这个技术,你可以把CPU从调度器域中取出,也就是说,在你指定一个任务在那个CPU上运行(使用taskset)之前,不会在那个CPU上调度任何任务。将一个CPU移出调度器域后,您可以借助将中断附加到该隔离CPU的技术,您可以通过/proc/irq/IRQ_NUMBER/smp_affinity完成此操作。现在,所有的中断都将由这个隔离的CPU处理,并且100%专用于该中断。使用您自己的IRQ例程,您可以完全控制中断处理。

希望这能有所帮助!

票数 0
EN

Stack Overflow用户

发布于 2016-08-13 16:33:39

你有没有想过用FIQ来解决这个问题。我们有一篇关于它的博客文章:http://free-electrons.com/blog/fiq-handlers-in-the-arm-linux-kernel/

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/38927607

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档