Я бы хотел написать драйвер с открытым исходным кодом для управления шаговыми двигателями в Linux. В этом случае, особенно для 3D-принтеров.ARM A7 Возможно использование прерывания Linux без прерывания?
Основная идея заключается в том, что водитель резервирует контакты на одном порту ввода-вывода, а затем управляет этими контактами одновременно. Он получает буфер, полный «переключать это, переключать эти» значения, а затем испускает их на порт, используя аппаратный таймер.
Теперь возникает вопрос: есть ли способ обработать конкретное аппаратное прерывание как можно быстрее?
Этот чип является Allwinner H3, и я использую ресурс TMR1 указанного чипа (IRQ 51). Я могу использовать это просто отлично, и она работает как прерывание, а также:
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-принтера, мне очень нравится более «стабильное» прерывание таймера.
Итак, мой вопрос: есть ли способ иметь очень короткую процедуру IRQ в Linux, которая имеет наивысший возможный приоритет? Или даже не заботится о планировщике Linux вообще, и просто «делает это»? В основном, обработчик IRQ, игнорируя то, что Linux думает, что это должно быть?
Ядро, с которым оно работает, предназначено именно для этой задачи. Обработчик будет как можно короче: выберете u32 из массива, напишите его в порт, сделайте.
Желательно, чтобы у меня было что-то, что просто игнорирует остальную часть Linux. Да, я знаю, что это не способ сделать это. Но это предназначено для довольно частного случая, поэтому у меня нет проблем с адаптацией регулярных исходных ядер для удовлетворения этих потребностей.
О, это напоминает мне, ядро 3.4.112 с подходящими исправлениями.
Любая помощь очень ценится.
Привет,
Chris
Вы посмотрели ядро RTAI? Thet накопители, такие как linux-cnc, и должны легко справляться с вашими требованиями времени. – tofro
Я нашел referneces для ядра RTAI, да. Но довольно печальная проблема заключается в том, что материал для чипов Allwinner частично присутствует в основном ядре. Th H3 там не существует. Таким образом, я должен исправлять себя через старое ядро 3.4.39, которое я встал до 3.4.112, а затем до версии preempt-rt. – ChrisK
Кроме того, у меня нет необходимости в некоторых сложных функциональных возможностях RT. Все, что я хочу (если это возможно), - это то, что один IRQ в GIC обрабатывается на голом металле. В этом случае IRQ 51 (для TMR1), практически не взаимодействующий с ядром. – ChrisK