Сделал модуль ядра под линукс 2.6.22.10. Смог инциализицровать прерывание:
Код
printk("Setting up IRQ: ");
interrupt_return = request_irq(IRQ_NUMBER, (void*) m_irq, IRQF_TRIGGER_FALLING, DEVICE_NAME, NULL);
if (interrupt_return != 0) {
printk("request IRQ return = %d ", interrupt_return);
}
printk("ok\n");
Обработчик прерывания выглядит след. образом:
Код
irq_handler_t m_irq(void) {
char ret_int;
BYTE DIG_DAT;
ret_int = FPGA_MEMORY_REGION[ADR_INTERRUPTS_REG];
printk("ret_int = %X", ret_int); //дебаг
if (ret_int == INT_DIGITAL_DATA) {
///// Interrupt for digital data
#ifdef DEBUG_MSG
printk("DIGITAL DATA Interrupt\n");
#endif
DIG_DAT = FPGA_MEMORY_REGION[ADR_DIG_STATE_LU_REG];
COUNT_DIGITAL_SENSOR(DIG_DAT);
}
}
ПРерывание генерирует ПЛИС, по чтению с регистра ADR_INTERRUPTS_REG (это адрес регистра в ПЛИС, читается при помощи SMC), ПЛИС возвращает INT0 в высокий уровень после чтения регистра ADR_INTERRUPTS_REG, после чего (если прерывание было то, какое я ожидаю - INT_DIGITAL_DATA), мне нужно прочитать еще 1 регистр - ADR_DIG_STATE_LU_REG. Т.е. грубо говоря на осциллографе я должен увидеть провал напряжения (прерывание по INT0), и где-то следом чтение из регистров.
Вообщем-то эту картину я и наблюдаю, однако задержка между прерыванием и чтением около 2-4
мкСек, что непомерно много для АРМ9. Что я делаю не так?
Кроме всего прочего посмотрел исходники ядра и поправил приоритет INT0 с 0 на 7. Т.е. оно сейчас имеет высший приоритет.
Быстрая обработка - критична - данных много и идут они довольно часто.
Также еще одна проблема - после вызова нескольких прерываний ядро валится в стэк (но остается работоспособным) с сообщением что за прерыванием никто не следит и надо бы загрузиться с опцией irqpoll. В чем тут может быть проблема?
Заметил еще один момент: если чтение с регистров идет друг за другом - то выполняется только последнее, если между чтениями натыкать cpu_relax(); то все хорошо... ПОчему так?
З.Ы. Бьюсь уже несколько дней - идей кончились... помогите!!!
Сообщение отредактировал MTh - May 22 2008, 01:46