2016-08-12 5 views
1

Linuxでステッピングモータを制御するためのオープンソースのコアドライバを書きたいと思っています。この場合、特に3Dプリンタの場合。ARM A7 LinuxのRAW割り込み処理は可能ですか?

基本的な考え方は、ドライバが1つのIOポートにピンを予約し、それらのピンを一度に操作することです。ハードウェアタイマーを使用して、「これをトグルしてトグルする」値で満杯になったバッファを受信し、ポートに送信します。

ここで問題は:特定のハードウェア割り込みをできるだけ早く処理する方法はありますか?

チップはAllwinner H3であり、チップ(IRQ51)の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の残りの部分をすべて無視するだけのことをしたいと思っています。はい、私はそれがそれを行う方法ではないことを知っています。しかし、これは特別なケースのためのものです。そのため、通常のカーネルソースをこれらのニーズに合わせて適応させることは難しいです。

ああ、カーネルは適切なpreempt-rtパッチで3.4.112です。

ご協力いただきまして誠にありがとうございます。ここで

挨拶、

クリス

+0

あなたはRTAIカーネルを見ましたか? Thetはlinux-cncのようなものを駆動し、あなたのタイミング要件に容易に対処するはずです。 – tofro

+0

私はRTAIカーネルへの参照を見つけました。しかし、むしろ悲しいことに、Allwinnerチップの素材は、部分的には主流のカーネルにしかないということです。 Th H3はそこに存在しない。そのため、古い3.4.39カーネルを使って自分自身にパッチを当てなければなりません。カーネルは3.4.112になってから、そのプリエンプト版までアップされています。 – ChrisK

+0

また、私は洗練されたRT機能を必要としません。 GICの1つのIRQがベアメタル上で処理されているということだけです(それが可能な場合でも)。この場合、IRQ51(TMR1の場合)は、カーネルとのやりとりがほとんどないか全くありません。 – ChrisK

答えて

0

は、この問題の一般解です。既存の割り込み処理ルーチンを上書きするカーネルモジュールを書くことができます。独自のルーチンで置き換えられます。irqを処理して、すべてのirqを既存のカーネル割り込み処理ルーチンにリダイレクトすることができます。低レベルのCPU命令を使用して割り込み記述ルーチン(lidt)の既存のアドレスを取得するx86 archでは可能です。私はそれもARMにとって可能なはずだと信じています。 Linuxはこの技術を利用してスケジューラードメインからCPUを取り出すことができます。つまり、その特定のCPU上で実行されるタスクを指定するまで(タスクセットを使用して)その特定のCPU上でタスクはスケジュールされません。あなたがスケジューラードメインからCPUを取り出した後は、その独立したCPUに割り込みをアフィンする技術の助けを借りて、あなたは/proc/irq/IRQ_NUMBER/smp_affinityによってそれを行うことができます。これですべての割り込みがこの独立したCPUによって処理され、100%がその割り込み専用になります。 IRQルーチンでは、割り込み処理を完全に制御できます。

うまくいけば、これが役に立ちます。

関連する問題