|
Прерывания (help) |
|
|
|
Apr 21 2005, 03:45
|
Группа: Новичок
Сообщений: 10
Регистрация: 20-04-05
Пользователь №: 4 305

|
Пишу прогу на c++, переопределяю прерывание от системного таймера на функцию например NewInt08(...). Устанавливаю частоту таймера ( outportb( 0x40, (char) cnt ); outportb( 0x40, (char)( cnt >> 8 ) ); ). Т.е. функция обработчик прерывания NewInt08(...) вызывается с той частотой с которой мне нужно (например 160 Hz). В обработчике снимаются данные и записываются на диск. Всё вродеб хорошо, но возникает проблема. Например при 160Hz после 100минут всё виснет наглухо.  Если убрать запись на диск, то программа проработала 5 часов без сбоев, далее просто выключил. Вопрос, в чём проблема? Не успевают обрабатыватся и записыватся данные и стек прерываний со временем переполняется? тогда можно ли его очищать? Или недопустимо записывать данные из прерываний? Тогда почему и какие могут быть решения проблемы? Пробовал уменьшать частоту при 150hz работает минут 140, при 100hz жадл 3 часа потом выключил.
|
|
|
|
|
Apr 21 2005, 07:43
|
Частый гость
 
Группа: Свой
Сообщений: 174
Регистрация: 9-07-04
Пользователь №: 305

|
Вот так я делал...работало всегда (старый добрый Borland v3) Похоже проблема с записью на диск. Точно знаю, что запись как таковая всегда откладывается до заполнения некоего буфера - отсюда и тормоза.
|
|
|
|
|
Apr 21 2005, 08:53
|
Профессионал
    
Группа: Свой
Сообщений: 1 526
Регистрация: 8-04-05
Пользователь №: 3 960

|
Цитата(rmihail @ Apr 21 2005, 06:45) Пишу прогу на c++, переопределяю прерывание от системного таймера на функцию например NewInt08(...). Устанавливаю частоту таймера ( outportb( 0x40, (char) cnt ); outportb( 0x40, (char)( cnt >> 8 ) ); ). Программа под ДОС. Запускать без загрузки каких-либо резидентных программ пытались (особенно дисковой направленности)? Старый вектор обрабатываете до или после своего модуля? Ваш модуль гарантировано с запасом укладывается в цикл прерывания?
|
|
|
|
|
Apr 21 2005, 08:55
|
Группа: Новичок
Сообщений: 10
Регистрация: 20-04-05
Пользователь №: 4 305

|
1) о каком контроллере идёт речь в Вашем сообщении. Речь идёт о компьютере сборщике: модуль центрального процессора Fastwel CPU 686 E (процессор Geode GX1- 300 МГц), модуль аналогового ввода-вывода AI16-5A (АЦП). На компе стоит урезаная вин98 (Будет дос).
2) О каком компиляторе идёт речь в Вашем сообщении. Borland C++ version 3.1. (Попробую скомпилять этим Borland C++ v5.02)
3) Как Вы узнаёте о том, что программа работает если она ничего никуда не пишет. Узнать о том, что идёт опрос схем можно по мерцанию диодов. Да и вобще если из программы удаляется только строка записи на диск и программа не виснет, то это уже по-моему говорит о том, что она работает (при условии что она и в режиме записи работает довольно долгое время).
4) Какая скорость записи на Ваш «диск». Почему приведённые данные для частоты прерываний никак не помогают узнать объём записываемых данных и скорость их записи? Скорость записы 20Mb/sec. За один тик таймера записывается 60bytes. Т.е. при частоте 160hz - 9600b/sec.
Тестировал время работы обработчика NewInt08(), за секунду выполняется 165-175 раз (естественно с записью). Даже при установке 200hz, программа работает минут 40. Обработчик прерывания от таймера при
Куда катиться этот мир?! Программы для МК на C++. На нём обычные программы и то писать на мой взгляд не стоит. Подскажите на чём писать такие программы?
|
|
|
|
|
Apr 21 2005, 09:16
|
Профессионал
    
Группа: Свой
Сообщений: 1 526
Регистрация: 8-04-05
Пользователь №: 3 960

|
Цитата(rmihail @ Apr 21 2005, 11:55) 1) о каком контроллере идёт речь в Вашем сообщении. На компе стоит урезаная вин98 (Будет дос). Под "чистым" ДОСом пробовали?
|
|
|
|
|
Apr 21 2005, 09:53
|
Группа: Новичок
Сообщений: 10
Регистрация: 20-04-05
Пользователь №: 4 305

|
Вобще под "чистым" досом с записью работает гораздо меньше времени, чем под виндой. Без записи работает отлично. "Точно знаю, что запись как таковая всегда откладывается до заполнения некоего буфера - отсюда и тормоза." Так и есть, даже судя по диоду обращения к жёсткому диску. Т.е. стоит попробовать заставить данные записыватся на диск каждые 160hz?
Скомпилял под Borland C++ v5.02, эффект примерно такойже. "Старый вектор обрабатываете до или после своего модуля?" Старый вектор обрабатывается после моей процедуры. Вот урезанный код обработки прерывания. void interrupt NewInt08(...) { static cnt = 0; disable(); // запрет прерываний
cnt++; // считаем сколько пропускать до вызова старого обработчика readallchannel(); // функция считывания и записи данных с АЦП if ( cnt >= BIOSTimerSpeed ) // true => вызвать старый обработчик {
gettime (&t); // читаем текущее время docommonwrite( (char *) &t,4,'t'); // запись текущего времени cnt = 0; enable(); // востановление прерываний SvInt08(); // вызов старого обработчика прерывания
} else { enable(); // востановление прерываний outportb(0x20,0x20); //конец прерывания }
} Возникла идея обрабатывать повешать флаг на считывание новых данных и старый обработчик вызывать раньше. В этом случаем новые прерывания по идеи должны пропускатся, либо вызыватся только старый обработчик.
|
|
|
|
|
Apr 21 2005, 10:17
|

Местный
  
Группа: Свой
Сообщений: 241
Регистрация: 22-12-04
Пользователь №: 1 610

|
Цитата(rmihail @ Apr 21 2005, 12:55) Куда катиться этот мир?! Программы для МК на C++. На нём обычные программы и то писать на мой взгляд не стоит. Подскажите на чём писать такие программы? Ну в начале я думал Вы под МК собираетесь на C++ програмировать. :-) Если говорить о ПК, то мой выбор — чистый C или ObjectiveC. Наличие объектов может приводить к печальным последствиям по быстродействию. Всякие опрашивающие вещи точно стоит писать на Си/asm. Что касается виндоуз и прочего ДОС есть две мысли: 1) написать запись на диск на ассемблере. 2) Поиграться в что-то под названием smartdrive (в windows/dos я не копенгаген, но помоему это и есть та самая буферизирующая сущность). Есть ещё третий путь: поставить FreeBSD и написать всё под неё. :-D
|
|
|
|
|
Apr 21 2005, 10:50
|

Adept
     
Группа: Свой
Сообщений: 3 469
Регистрация: 6-12-04
Из: Novosibirsk
Пользователь №: 1 343

|
Цитата(sK0T @ Apr 21 2005, 16:17) Цитата(rmihail @ Apr 21 2005, 12:55) Куда катиться этот мир?! Программы для МК на C++. На нём обычные программы и то писать на мой взгляд не стоит. Подскажите на чём писать такие программы? Ну в начале я думал Вы под МК собираетесь на C++ програмировать. :-) Если говорить о ПК, то мой выбор — чистый C или ObjectiveC. Наличие объектов может приводить к печальным последствиям по быстродействию. Всякие опрашивающие вещи точно стоит писать на Си/asm. На чем основано такое заявление? Я вот вполне успешно пишу на С++ в том числе и для МК. По оверхеду почти то же самое, что и на С. Надо просто знать средство и уметь им пользоваться. А безобразную программу можно на любом языке наделать, в т.ч. и на асме. На нем даже проще. Кстати, где Вы видели ObjectiveC для МК? Для какого МК, если не секрет?
--------------------
«Отыщи всему начало, и ты многое поймёшь» К. Прутков
|
|
|
|
|
Apr 21 2005, 14:26
|
Профессионал
    
Группа: Свой
Сообщений: 1 526
Регистрация: 8-04-05
Пользователь №: 3 960

|
Цитата(rmihail @ Apr 21 2005, 12:53) enable(); // востановление прерываний outportb(0x20,0x20); //конец прерывания } } А зачем Вы контроллер превываний дергаете перед выходом?. Это же уже сделано в старом обработчике. По-моему (могу ошибаться) прерывания с диска имеют более высокий приоритет, чем таймер. Поэтому запрет прерываний в таймерной секции с последующим EOI по-моему может при определенном стечении обстоятельств вызвать потерю прерывания с диска. Попробуйте убрать обращение к контроллеру преряваний.
|
|
|
|
|
Apr 26 2005, 12:36
|

Частый гость
 
Группа: Свой
Сообщений: 146
Регистрация: 4-11-04
Из: Московская область
Пользователь №: 1 040

|
Цитата(rmihail @ Apr 21 2005, 12:53) void interrupt NewInt08(...) { static cnt = 0; disable(); // запрет прерываний Дизайбл делать не надо - и так уже дизэйбл, на аппаратном уровне Цитата(rmihail @ Apr 21 2005, 12:53) cnt++; // считаем сколько пропускать до вызова старого обработчика readallchannel(); // функция считывания и записи данных с АЦП if ( cnt >= BIOSTimerSpeed ) // true => вызвать старый обработчик {
gettime (&t); // читаем текущее время docommonwrite( (char *) &t,4,'t'); // запись текущего времени cnt = 0; enable(); // востановление прерываний энэйбл тут - это подозрительно. Это даст возможность вложенных прерываний. Это очень тонкий момент, лучше так не делать. Цитата(rmihail @ Apr 21 2005, 12:53) SvInt08(); // вызов старого обработчика прерывания
} else { enable(); // востановление прерываний outportb(0x20,0x20); //конец прерывания Это ...."полный привет".. !!! Дело в том, что обращение к интеррапт-контроллеру само по себе может вызвать аппаратное шевеление вывода INT. Что приведет к генерации дополнительного прерывания. В таких случаях вполне возможна непрерывная генерация. Основанная не неверно написанном обработчике прерываний. Кроме того - энейбл совершенно бесполезен в конце обработчика. Так же, как бесполезен дизэйбл в начале обработчика. Ибо после окончания обработчика он (энейбл) будет сделан аппаратно...
--------------------
- ЗАМЕНЯТЬ ДЕТАЛИ НА ХОДУ ВОСПРЕЩАЕТСЯ !!! -
|
|
|
|
|
Apr 27 2005, 05:01
|
Группа: Новичок
Сообщений: 10
Регистрация: 20-04-05
Пользователь №: 4 305

|
На самом деле енавле и дизабле хоть ставь хоть нет эффект тотже. Сначала их не было, потом начал всякие эксперименты ставить. Так что проблема не в этом
|
|
|
|
|
Apr 27 2005, 11:38
|

Частый гость
 
Группа: Свой
Сообщений: 146
Регистрация: 4-11-04
Из: Московская область
Пользователь №: 1 040

|
Цитата(rmihail @ Apr 27 2005, 08:01) На самом деле енавле и дизабле хоть ставь хоть нет эффект тотже. Сначала их не было, потом начал всякие эксперименты ставить. Так что проблема не в этом  Эффект все-таки "не тот же". По крайней мере процедура выполняется медленнее. Кроме того, результат в таких случаях носит вероятностный характер. "Это надо знать точно". Ни понять, не заосциллографировать (чуть язык не сломал  ) тут ничего не удасться. Цитата docommonwrite( (char *) &t,4,'t'); // запись текущего времени cnt = 0;
enable(); // востановление прерываний Это не будет работать потому, что энейбл и дизэйбл - это разрешение/запрещение прерываний центральному процессору. Кстати, лучше делать так: asm sti; // enable asm cli; // disable Но система прерываний (в Вашей программе) не приведена в исходное состояние. Это значит, никаких прерываний не будет .Независимо от их разрешения. Цитата enable(); // востановление прерываний SvInt08(); // вызов старого обработчика прерывания А вот это, видимо, Ваша проблема. Дело в том, что прерывания "активизируются" командой INTx. Вот как она работает: asm pushf; !! asm cli; asm call dword ptr [4*x] А заканчивается прерывание командой IRET, которая: asm pop ip asm pop cs asm popf Точнее вы и сами можете почитать. <_< Поэтому нельзя просто так вызвать старый обработчик. надо что-то вроде: asm pushf; OldVector (); При этом надо быть уверенным, что адрес старого обработчика спасен как (far *) Я бы посоветовал вам сделать (для начала) прерывание по рыбе: void interrupt some_routine (void) { // для начала сбросим систему прерываний: RESET_MASTER_IC // это outportb (0x20,0x20); // RESET_SLAVE_IC // это outportb (oxA0,0x20); - если используется слэйв . . // тело обработчика . . } И фсе ! Если это будет работать устойчиво, тогда можно будет ставить еще эксперименты.  В любом случае, все операции с контроллерами прерываний должны производиться когда DISABLE !!!!!
--------------------
- ЗАМЕНЯТЬ ДЕТАЛИ НА ХОДУ ВОСПРЕЩАЕТСЯ !!! -
|
|
|
|
|
May 11 2005, 10:18
|
Группа: Новичок
Сообщений: 10
Регистрация: 20-04-05
Пользователь №: 4 305

|
Цитата(vvs157 @ Apr 21 2005, 17:26) А зачем Вы контроллер превываний дергаете перед выходом?. Это же уже сделано в старом обработчике. По-моему (могу ошибаться) прерывания с диска имеют более высокий приоритет, чем таймер. Поэтому запрет прерываний в таймерной секции с последующим EOI по-моему может при определенном стечении обстоятельств вызвать потерю прерывания с диска. Попробуйте убрать обращение к контроллеру преряваний. Т.к. прерывания от таймера у меня возникают не 18.2 раза в секунду, а столько сколько мне нужно (в зависимости от count: outportb( 0x40, (char) count); outportb( 0x40, (char)( count >> 8 ) ); задаётся частота возникновения прерываний от таймера), то и стандартный обработчик таймера я вызываю не всегда. В переменной BIOSTimerSpeed хранится число прерываний котороые я должен пропустить прежде чем вызвать стандартный обработчик. if ( cnt >= BIOSTimerSpeed ) { cnt = 0; SvInt08(); } else { outportb(0x20,0x20); } Поэтому, если не вызван стандартный обработчик то нужно outportb(0x20,0x20); Прерывание с диска имеют более низкий приоритет, чем от таймера. Однако возможно изменение приоритетов в рамках приоритетного кольца. Попробую поизменять приоритеты...
|
|
|
|
|
May 11 2005, 10:46
|
Группа: Новичок
Сообщений: 10
Регистрация: 20-04-05
Пользователь №: 4 305

|
Цитата(-Tумблер- @ Apr 27 2005, 14:38) Но система прерываний (в Вашей программе) не приведена в исходное состояние. Это значит, никаких прерываний не будет .Независимо от их разрешения. Цитата enable(); // востановление прерываний SvInt08(); // вызов старого обработчика прерывания А вот это, видимо, Ваша проблема. Дело в том, что прерывания "активизируются" командой INTx. Вот как она работает: asm pushf; !! asm cli; asm call dword ptr [4*x] SvInt08 = getvect( 8 ); Поэтому вызов старого обработчика сводится к обычному вызову процедуры SvInt08(); Не вижу здесь ничего плохого.
|
|
|
|
|
May 12 2005, 02:38
|
Группа: Новичок
Сообщений: 10
Регистрация: 20-04-05
Пользователь №: 4 305

|
Да, очень интересно. Если можно выложите плизз сюда или на мыло: guest@gorodok.net.
|
|
|
|
|
May 12 2005, 06:49
|

Местный
  
Группа: Свой
Сообщений: 272
Регистрация: 17-01-05
Из: Ростов-на-Дону
Пользователь №: 2 018

|
Выкладываю. Там всё написано без комментариев, поэтому сейчас накропал текстовый файлик с кратким описанием. За давностью лет многое забылось, но основные моменты, думаю, я осветил. Там же есть образец использования этой штуки, надёрганный из двух (!) рабочих программ. Так что если найдёте там логические и прочие нестыковки - не удивляйтесь.  Если возникнут вопросы - спрашивайте, буду отвечать. А вообще там всё трогательно просто, так что разобраться будет несложно. Успехов!
--------------------
/* Всё хорошо в меру. */
|
|
|
|
|
May 13 2005, 08:03
|
Группа: Новичок
Сообщений: 10
Регистрация: 20-04-05
Пользователь №: 4 305

|
Цитата(Vitёk @ May 12 2005, 09:49) Выкладываю. Там всё написано без комментариев, поэтому сейчас накропал текстовый файлик с кратким описанием. За давностью лет многое забылось, но основные моменты, думаю, я осветил. Там же есть образец использования этой штуки, надёрганный из двух (!) рабочих программ. Так что если найдёте там логические и прочие нестыковки - не удивляйтесь.  Если возникнут вопросы - спрашивайте, буду отвечать. А вообще там всё трогательно просто, так что разобраться будет несложно. Успехов!  Спасибо, проблему решил.  Вынес все процедуры считывания и записи из обработчика прерывания. Загнал их в бесконечный цикл (почти бесконечный ). В обработчике сделал флаг, когда считывать. Всё работает. ЗЫ: За мессенджер особое спасибо. Поразбираюсь.
|
|
|
|
3 чел. читают эту тему (гостей: 3, скрытых пользователей: 0)
Пользователей: 0
|
|
|