ARM A7 Linux原始中断处理可能吗?
我想写一个开源的核心驱动程序来控制Linux中的步进电机。在这种情况下,尤其是3D打印机。ARM A7 Linux原始中断处理可能吗?
其基本思想是驱动程序在一个IO端口上预留引脚,然后一次操作这些引脚。它接收一个缓冲区,其中充满了“切换该值,切换该值”,然后使用硬件定时器将这些值发送到端口。
现在的问题是:有没有办法尽可能快地处理特定的硬件中断?
该问题的芯片是Allwinner H3,而且我正在使用该芯片(IRQ 51)的TMR1资源。我可以用它蛮好的,它可以作为一个中断,以及:
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与适当的抢占rt补丁。
任何帮助,非常感谢。
问候,
克里斯
下面是对这个问题的通用解决方案。您可以编写一个内核模块来覆盖现有的中断处理例程,并由您自己的例程替换,您可以在其中处理感兴趣的irq,并将所有irq重定向到现有的内核中断处理例程。 x86 arch可能会得到低级CPU指令来获取中断描述例程的现有地址(lidt
)。我相信它也应该可以用于ARM。现在,Linux具有CPU隔离技术isolcpus
,通过使用这种技术,您可以将CPU从调度程序域中取出,即在您指定要在该特定CPU上运行的任务(使用taskset)之前,不会在该特定CPU上调度任何任务。将CPU从调度程序域中取出后,可以利用对该隔离CPU仿造中断的技术,可以通过/proc/irq/IRQ_NUMBER/smp_affinity
来完成。现在所有的中断都将由该隔离CPU处理,并且100%专用于该中断。通过您自己的IRQ例程,您可以完全控制中断处理。
希望这会有所帮助!
你看过RTAI内核吗? Thet驱动像linux-cnc这样的东西,并且应该很容易地满足你的时序要求。 – tofro
我发现引用了RTAI内核,是的。但令人悲伤的问题是,Allwinner芯片的功能仅部分在主流内核中。那里H3不存在。因此,我必须通过旧的3.4.39内核补丁,然后到3.4.112,然后达到抢先版本。 – ChrisK
此外,我不需要一些复杂的RT功能。我想要的(如果可能的话)是GIC中的一个IRQ是在裸机上处理的。在这种情况下,IRQ 51(对于TMR1)几乎没有任何内核交互。 – ChrisK