diff --git a/utils/int-attach/README.md b/utils/int-attach/README.md index d9012eb..4ee26e6 100644 --- a/utils/int-attach/README.md +++ b/utils/int-attach/README.md @@ -1,28 +1,33 @@ ### int-attach -Навесить обработчик прерывания и выводить отладочное сообщение при его возникновении +Навесить обработчик прерывания и выводить отладочное сообщение при его возникновении. ### Синтаксис -```int-attach -i N``` +```int-attach -i N -m -p P``` ### Опции -- **-i номер_прерывания** - - навесить обработчик на указанный номер +-i номер_прерывания Навесить обработчик на указанный номер. +-m Маскировать прерывание в обработчике и размаскировать в основном потоке. +-p период_мс Подсчитывать количество прерываний за указанный период времени (в миллисекундах). ### Описание Утилита int-attach навешивает минимальный обработчик на заданный номер прерывания и выводит отладочное сообщение при возникновении этого прерывания. -Подключаемый обработчик прерывания содержит минимальный код, увеличивающий счётчик количества перехваченных прерываний и маскирующий прерывание. Размаскирование прерывания выполняется в основном потоке функции main() после вывода отладочного сообщения в консоль. +Подключаемый обработчик прерывания содержит минимальный код, увеличивающий счётчик с количеством полученных прерываний. +При задании опции -m прерывание маскируется в обработчике с помощью InterruptMask() и размаскируется после вывода отладочного сообщения в консоль. +При задании опции -p производится подсчёт поличества прерываний за указанный период времени. -Может использоваться для отладки и проверки того, что указанное прерывание возникает в ожидаемый момент времени, например, при обращении к аппаратуре, отправка сообщения в COM порт, работа с диском и т.п. +Утилита может использоваться для отладки работы прерываний и проверки того, что указанное прерывание возникает в ожидаемый момент времени, например, при работе с аппаратурой, получении данных из COM порта и т.п. Одновременно можно запустить несколько копий программы с различными номерами прерываний. ### Предостережения -Учтите, что вывод отладочного сообщения достаточно длительная операция и на это время прерывание будет оставаться замаскированным, что значительно увеличит задержку его обработки в основном драйвере/программ и может нарушить их работу. +Учтите, что при задании флага -m и маскировании прерывания может нарушиться работа драйвера или программы, отвечающих за обработку этого прерывания, т.к. вывод отладочного сообщения достаточно длительная операция и на это время прерывание будет оставаться замаскированным. ### Примеры -Навесить обработчик на прерывание 10 -```int-attach -i 10 &``` +Навесить обработчик на прерывание номер 10 +```int-attach -i 10``` + +Подсчитать количество прерываний за 1 секунду (1000мс) +```int-attach -i 10 -p 1000``` diff --git a/utils/int-attach/int-attach.c b/utils/int-attach/int-attach.c index 4ca66df..c0579aa 100644 --- a/utils/int-attach/int-attach.c +++ b/utils/int-attach/int-attach.c @@ -10,21 +10,36 @@ #include #include #include +#include +#include struct sigevent int_event; -int id = -1; -unsigned long int_n = 1; -volatile unsigned long int_conter = 0; +int id = -1; +int interrupt_n = -1; +int mask_flag = 0; +unsigned period_ns = 0; +volatile unsigned long int_counter = 0; +volatile uint64_t prev_nsec = 0; const struct sigevent *handler( void *area, int id ) { - InterruptMask( int_n, id ); + if ( mask_flag ) + InterruptMask( interrupt_n, id ); - int_conter++; + int_counter++; - return (&int_event); + if ( !period_ns ) + return (&int_event); + else { + if ( (SYSPAGE_ENTRY( qtime )->nsec - prev_nsec) > period_ns ) + { + prev_nsec = SYSPAGE_ENTRY( qtime )->nsec; + return (&int_event); + } else + return (NULL); + } } @@ -41,38 +56,66 @@ int main( int argc, char **argv ) printf( "Interrupt attach program \n" ); - while ( (opt = getopt ( argc, argv, "i:" )) != -1 ) + while ( (opt = getopt( argc, argv, "i:p:m" )) != -1 ) { switch ( opt ) { case 'i': - int_n = strtoul( optarg, NULL, 0 ); + interrupt_n = strtoul( optarg, NULL, 0 ); break; + + case 'p': + period_ns = strtoul( optarg, NULL, 0 ); + period_ns *= 1000 * 1000; // nanoseconds + break; + + case 'm': + mask_flag = 1; + break; + + default: + printf( "Unsupported option.\n" ); + return (-1); } } - if( int_n < 0 ) + if( interrupt_n < 0 ) + { + printf( "Incorrect interrupt number %d \n", interrupt_n ); return (-1); - else - printf( "Attaching handler for interrupt %lu ( 0x%lX ) \n\n", int_n, int_n ); + } else + printf( "Attaching handler for interrupt %u ( 0x%X ) \n\n", interrupt_n, interrupt_n ); int_event.sigev_notify = SIGEV_INTR; - // register an interrupt handler - id = InterruptAttach( int_n, &handler, NULL, 0, 0 ); + // Attach interrupt handler + id = InterruptAttach( interrupt_n, &handler, NULL, 0, 0 ); if ( id == -1 ) { - perror( " Cannot attach interrupt handler " ); + perror( "Cannot attach interrupt handler" ); return (-1); } + if ( period_ns ) + { + printf( "Counting number of interrupts %u ( 0x%X ) per %u milliseconds \n", interrupt_n, interrupt_n, period_ns / 1000000 ); + int_counter = 0; + prev_nsec = SYSPAGE_ENTRY( qtime )->nsec; + } + while ( 1 ) { InterruptWait( 0, NULL ); - printf( "Got interrupt %lu ( 0x%lX ) #%4ld\n", int_n, int_n, int_conter ); - InterruptUnmask( int_n, id ); + if ( int_counter ) + printf( "Interrupt %u ( 0x%X ) : %8ld \n", interrupt_n, interrupt_n, int_counter ); + + if ( period_ns ) + int_counter = 0; + + if ( mask_flag ) + InterruptUnmask( interrupt_n, id ); } InterruptDetach( id ); diff --git a/utils/int-attach/int-attach.use b/utils/int-attach/int-attach.use index 52072bc..1f91001 100644 --- a/utils/int-attach/int-attach.use +++ b/utils/int-attach/int-attach.use @@ -1,5 +1,7 @@ %C - interrupt attach Options: -i - Attach interrupt handler for interrupt (InterruptAttach() is used). - Interrupt is masked in interrupt handler and then unmasked in main thread. +-i interrupt_num Attach interrupt handler for interrupt . +-m Mask interrupt in interrupt handler and then unmask in main thread. +-p period_ms Count number of interrupts for specified period. +