3

CONFIG_PREEMPT_RT パッチを適用した Linux カーネル (3.8.13) を実行している Freescales imx.233 で、IRQ/ISR のパフォーマンスに少し一貫性がありません。なぜこのプロセッサ (ARM9、454mhz) が 74kHz の IRQ 要求にも対応できないのか、少し驚いています。

私のカーネル構成では、次のフラグを設定しました。

CONFIG_TINY_PREEMPT_RCU=y
CONFIG_PREEMPT_RCU=y
CONFIG_PREEMPT=y
CONFIG_PREEMPT_RT_BASE=y
CONFIG_HAVE_PREEMPT_LAZY=y
CONFIG_PREEMPT_LAZY=y
CONFIG_PREEMPT_RT_FULL=y
CONFIG_PREEMPT_COUNT=y
CONFIG_DEBUG_PREEMPT=y

システム上では基本的に何も実行されていません (buildroot によって作成されます)。割り込みとして機能する 74kHz のパルスを生成するように PWM を設定しました。次に、ISR で別の GPIO 出力ピンをトリガーし、出力を確認します。私が見つけたのは、割り込みを見逃すことがあるということです-逃した割り込みをここで見ることができます:

割り込みを逃した

また、出力ピンのトリガーは少し一貫していないようです。出力ピンは通常「5% ウィンドウ」内でトリガーされますが、それでも許容される可能性があります。しかし、ピンをトリガーするだけでなく、データ転送ロジックの実装を開始すると、さらに問題が発生するのではないかと心配しています...

私の単純なドライバーコードは次のようになります。

#needed includes

uint16_t INPUT_IRQ = 39;
uint16_t OUTPUT_GPIO = 38;

struct test_device *device;

//Prototypes
void irqtest_exit(void);
int irqtest_init(void);
void free_device(void);

//Default functions
module_init(irqtest_init);
module_exit(irqtest_exit);

//triggering flag
uint16_t pulse = 0x1;

irqreturn_t irq_handle_function(int irq, void *device_id)
{
pulse = !pulse;
gpio_set_value(OUTPUT_GPIO, pulse);

return IRQ_HANDLED;
}

struct test_device { 
    int huuhaa;
};

void free_device() {
if (device)
    kfree(device);
}   

int irqtest_init(void) {
    int result = 0;

    device = kmalloc(sizeof *device, GFP_KERNEL);
    device->huuhaa = 10;

    printk("IRB/irqtest_init: Inserting IRQ module\n"); 

    printk("IRB/irqtest_init: Requesting GPIO (%d)\n", INPUT_IRQ); 
    result = gpio_request_one(INPUT_IRQ, GPIOF_IN, "PWM input");

    if (result != 0) {
        free_device();
        printk("IRB/irqtest_init: Failed to set GPIO (%d) as input.. exiting\n", INPUT_IRQ);
        return -EINVAL;
    } 
    result = gpio_request_one(OUTPUT_GPIO, GPIOF_OUT_INIT_LOW , "IR OUTPUT");
    if (result != 0) {
        free_device();
        printk("IRB/irqtest_init: Failed to set GPIO (%d) as output.. exiting\n", OUTPUT_GPIO);
        return -EINVAL;
    } 

    //Set our desired interrupt line as input
    result = gpio_direction_input(INPUT_IRQ);

    if (result != 0) {
        printk("IRB/irqtest_init: Failed to set IRQ as input.. exiting\n");
        free_device();
        return -EINVAL;
    }   

    //Set flags for our interrupt, guessing here..
    irq_flags |=  IRQF_NO_THREAD;
    irq_flags |=  IRQF_NOBALANCING;
    irq_flags |=  IRQF_TRIGGER_RISING;
    irq_flags |=  IRQF_NO_SOFTIRQ_CALL;

    //register interrupt
    result = request_irq(gpio_to_irq(INPUT_IRQ), irq_handle_function, irq_flags, "irq testing", device);

    if (result != 0) {
        printk("IRB/irqtest_init: Failed to reserve GPIO 38\n");
        return -EINVAL;
    } 
    printk("IRB/irqtest_init: insert success\n"); 
    return 0;
}

void irqtest_exit(void) {
    if (device)
        kfree(device);
    gpio_free(INPUT_IRQ);
    gpio_free(OUTPUT_GPIO);

    printk("IRB/irqtest_exit: Removing irqtest module\n");
}


int irqtest_open(struct inode *inode, struct file *filp) {return 0;}
int irqtest_release(struct inode *inode, struct file *filp) {return 0;}

システムでは、ドライバーがロードされた後、次の割り込みが登録されています。

# cat /proc/interrupts 
       CPU0       
 16:      36379         -  MXS Timer Tick
 17:          0         -  mxs-spi
 18:       2103         -  mxs-dma
 60:          0  gpio-mxs  irq testing
118:          0         -  mxs-spi
119:          0         -  mxs-dma
120:          0         -  RTC alarm
124:          0         -  8006c000.serial
127:      68050         -  uart-pl011
128:        151         -  ci13xxx_imx
Err:          0

IRQ に宣言するフラグが適切かどうか疑問に思います。この構成では、コンソールに到達できなくなっていることに気付きました。そのため、カーネルは現在、この 74kHz トリガーのサービスに完全に消費されているようです..これは正しくありませんか? これはデータ転送中だけなので、私にとっては大したことではないと思いますが、それでも何か間違っていると感じています..

また、レジスタをioremapでマップし、直接メモリ書き込みで出力をトリガーする方が効率的でしょうか?

割り込みの優先度をさらに高くする方法はありますか? または、データ転送中 (~400ms) カーネルを何らかの方法でロックし、何らかの方法で出力のタイミングを生成できますか?

編集: /proc/interrupts 出力を質問に追加するのを忘れました...

4

3 に答える 3

0

このフラグを試してください:

int irq_flags;
...
irq_flags = IRQF_TRIGGER_RISING | IRQF_EARLY_RESUME

カーネル 3.8.11 があり、IRQF_NO_SOFTIRQ_CALL 定義が見つかりません。3.8.13専用ですか?また、irq_flags が定義されていることもわかりませんでした。それはどこにある?

于 2013-06-22T10:28:29.923 に答える