реклама на сайте
подробности

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> Прерывания (help)
rmihail
сообщение Apr 21 2005, 03:45
Сообщение #1





Группа: Новичок
Сообщений: 10
Регистрация: 20-04-05
Пользователь №: 4 305



Пишу прогу на c++, переопределяю прерывание от системного таймера на функцию например NewInt08(...). Устанавливаю частоту таймера
( outportb( 0x40, (char) cnt );
outportb( 0x40, (char)( cnt >> 8 ) ); ).
Т.е. функция обработчик прерывания NewInt08(...) вызывается с той частотой с которой мне нужно (например 160 Hz). В обработчике снимаются данные и записываются на диск.
Всё вродеб хорошо, но возникает проблема. Например при 160Hz после 100минут всё виснет наглухо. cranky.gif Если убрать запись на диск, то программа проработала 5 часов без сбоев, далее просто выключил.
Вопрос, в чём проблема? Не успевают обрабатыватся и записыватся данные и стек прерываний со временем переполняется? тогда можно ли его очищать?
Или недопустимо записывать данные из прерываний? Тогда почему и какие могут быть решения проблемы?
Пробовал уменьшать частоту при 150hz работает минут 140, при 100hz жадл 3 часа потом выключил.
Go to the top of the page
 
+Quote Post
sK0T
сообщение Apr 21 2005, 04:36
Сообщение #2


Местный
***

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



Куда катиться этот мир?! Программы для МК на C++. На нём обычные программы и то писать на мой взгляд не стоит.

Попробуем разобраться для начала вот в каком вопросе: почему Вы так уверены, что каждый на этом форуме понимает:
1) о каком контроллере идёт речь в Вашем сообщении.
2) О каком компиляторе идёт речь в Вашем сообщении.
3) Как Вы узнаёте о том, что программа работает если она ничего никуда не пишет.
4) Какая скорость записи на Ваш «диск». Почему приведённые данные для частоты прерываний никак не помогают узнать объём записываемых данных и скорость их записи?
Go to the top of the page
 
+Quote Post
nameless
сообщение Apr 21 2005, 07:43
Сообщение #3


Частый гость
**

Группа: Свой
Сообщений: 174
Регистрация: 9-07-04
Пользователь №: 305



Вот так я делал...работало всегда (старый добрый Borland v3) Похоже проблема с записью на диск. Точно знаю, что запись как таковая всегда откладывается до заполнения некоего буфера - отсюда и тормоза.
Прикрепленные файлы
Прикрепленный файл  asEXAMPLE.rar ( 1.82 килобайт ) Кол-во скачиваний: 46
 
Go to the top of the page
 
+Quote Post
vvs157
сообщение Apr 21 2005, 08:53
Сообщение #4


Профессионал
*****

Группа: Свой
Сообщений: 1 526
Регистрация: 8-04-05
Пользователь №: 3 960



Цитата(rmihail @ Apr 21 2005, 06:45)
Пишу прогу на c++, переопределяю прерывание от системного таймера на функцию например NewInt08(...). Устанавливаю частоту таймера
( outportb( 0x40, (char) cnt );
outportb( 0x40, (char)( cnt >> 8 ) ); ).
*


Программа под ДОС. Запускать без загрузки каких-либо резидентных программ пытались (особенно дисковой направленности)? Старый вектор обрабатываете до или после своего модуля? Ваш модуль гарантировано с запасом укладывается в цикл прерывания?
Go to the top of the page
 
+Quote Post
rmihail
сообщение Apr 21 2005, 08:55
Сообщение #5





Группа: Новичок
Сообщений: 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++. На нём обычные программы и то писать на мой взгляд не стоит.
Подскажите на чём писать такие программы?
Go to the top of the page
 
+Quote Post
vvs157
сообщение Apr 21 2005, 09:16
Сообщение #6


Профессионал
*****

Группа: Свой
Сообщений: 1 526
Регистрация: 8-04-05
Пользователь №: 3 960



Цитата(rmihail @ Apr 21 2005, 11:55)
1) о каком контроллере идёт речь в Вашем сообщении.
На компе стоит урезаная вин98 (Будет дос).
*


Под "чистым" ДОСом пробовали?
Go to the top of the page
 
+Quote Post
rmihail
сообщение Apr 21 2005, 09:53
Сообщение #7





Группа: Новичок
Сообщений: 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); //конец прерывания
}

}

Возникла идея обрабатывать повешать флаг на считывание новых данных и старый обработчик вызывать раньше. В этом случаем новые прерывания по идеи должны пропускатся, либо вызыватся только старый обработчик.
Go to the top of the page
 
+Quote Post
sK0T
сообщение Apr 21 2005, 10:17
Сообщение #8


Местный
***

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



Цитата(rmihail @ Apr 21 2005, 12:55)
Куда катиться этот мир?! Программы для МК на C++. На нём обычные программы и то писать на мой взгляд не стоит.
  Подскажите на чём писать такие программы?
*


Ну в начале я думал Вы под МК собираетесь на C++ програмировать. :-)
Если говорить о ПК, то мой выбор — чистый C или ObjectiveC. Наличие объектов может приводить к печальным последствиям по быстродействию. Всякие опрашивающие вещи точно стоит писать на Си/asm.

Что касается виндоуз и прочего ДОС есть две мысли:
1) написать запись на диск на ассемблере.
2) Поиграться в что-то под названием smartdrive (в windows/dos я не копенгаген, но помоему это и есть та самая буферизирующая сущность).

Есть ещё третий путь: поставить FreeBSD и написать всё под неё. :-D
Go to the top of the page
 
+Quote Post
dxp
сообщение Apr 21 2005, 10:50
Сообщение #9


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 для МК? Для какого МК, если не секрет?


--------------------
«Отыщи всему начало, и ты многое поймёшь» К. Прутков
Go to the top of the page
 
+Quote Post
vvs157
сообщение Apr 21 2005, 14:26
Сообщение #10


Профессионал
*****

Группа: Свой
Сообщений: 1 526
Регистрация: 8-04-05
Пользователь №: 3 960



Цитата(rmihail @ Apr 21 2005, 12:53)
      enable();                      // востановление прерываний
      outportb(0x20,0x20);      //конец прерывания
    }

}

*


А зачем Вы контроллер превываний дергаете перед выходом?. Это же уже сделано в старом обработчике. По-моему (могу ошибаться) прерывания с диска имеют более высокий приоритет, чем таймер. Поэтому запрет прерываний в таймерной секции с последующим EOI по-моему может при определенном стечении обстоятельств вызвать потерю прерывания с диска. Попробуйте убрать обращение к контроллеру преряваний.
Go to the top of the page
 
+Quote Post
-Tумблер-
сообщение Apr 26 2005, 12:36
Сообщение #11


Частый гость
**

Группа: Свой
Сообщений: 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);      //конец прерывания


Это ...."полный привет".. !!! blink.gif

Дело в том, что обращение к интеррапт-контроллеру
само по себе может вызвать аппаратное шевеление вывода INT.
Что приведет к генерации дополнительного прерывания.
В таких случаях вполне возможна непрерывная генерация.
Основанная не неверно написанном обработчике прерываний.
Кроме того - энейбл совершенно бесполезен в конце обработчика.
Так же, как бесполезен дизэйбл в начале обработчика. biggrin.gif
Ибо после окончания обработчика он (энейбл) будет сделан аппаратно...
smile.gif


--------------------

- ЗАМЕНЯТЬ ДЕТАЛИ НА ХОДУ ВОСПРЕЩАЕТСЯ !!! -
Go to the top of the page
 
+Quote Post
rmihail
сообщение Apr 27 2005, 05:01
Сообщение #12





Группа: Новичок
Сообщений: 10
Регистрация: 20-04-05
Пользователь №: 4 305



На самом деле енавле и дизабле хоть ставь хоть нет эффект тотже. Сначала их не было, потом начал всякие эксперименты ставить. Так что проблема не в этом sad.gif
Go to the top of the page
 
+Quote Post
-Tумблер-
сообщение Apr 27 2005, 11:38
Сообщение #13


Частый гость
**

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



Цитата(rmihail @ Apr 27 2005, 08:01)
На самом деле енавле и дизабле хоть ставь хоть нет эффект тотже. Сначала их не было, потом начал всякие эксперименты ставить. Так что проблема не в этом  sad.gif


Эффект все-таки "не тот же".
По крайней мере процедура выполняется медленнее.
Кроме того, результат в таких случаях носит вероятностный
характер.
"Это надо знать точно". Ни понять, не заосциллографировать
(чуть язык не сломал smile.gif ) тут ничего не удасться.

Цитата
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); - если используется слэйв
.
.
// тело обработчика
.
.
}

И фсе !
Если это будет работать устойчиво, тогда можно будет ставить
еще эксперименты.

excl.gif В любом случае, все операции с контроллерами прерываний
должны производиться когда DISABLE !!!!! excl.gif
smile.gif


--------------------

- ЗАМЕНЯТЬ ДЕТАЛИ НА ХОДУ ВОСПРЕЩАЕТСЯ !!! -
Go to the top of the page
 
+Quote Post
rmihail
сообщение May 11 2005, 10:18
Сообщение #14





Группа: Новичок
Сообщений: 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);
Прерывание с диска имеют более низкий приоритет, чем от таймера. Однако возможно изменение приоритетов в рамках приоритетного кольца. Попробую поизменять приоритеты...
Go to the top of the page
 
+Quote Post
rmihail
сообщение May 11 2005, 10:46
Сообщение #15





Группа: Новичок
Сообщений: 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(); Не вижу здесь ничего плохого.
Go to the top of the page
 
+Quote Post

2 страниц V   1 2 >
Reply to this topicStart new topic
2 чел. читают эту тему (гостей: 2, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 16th June 2025 - 19:42
Рейтинг@Mail.ru


Страница сгенерированна за 0.02663 секунд с 7
ELECTRONIX ©2004-2016