Форум программистов, компьютерный форум, киберфорум
Free Pascal
Войти
Регистрация
Восстановить пароль
 
Рейтинг 5.00/7: Рейтинг темы: голосов - 7, средняя оценка - 5.00
41 / 41 / 36
Регистрация: 23.11.2006
Сообщений: 151
1

Обработка аппаратных прерываний

10.01.2017, 18:07. Просмотров 1437. Ответов 8
Метки нет (Все метки)


Доброго вечера. Уважаемые форумчане, кто нибудь сталкивался с таким? Необходимо написать подпрограмму обработки аппаратного прерывания системного таймера для генерации звука через каждые 5 секунд. Функция Delay() не в счёт. Прошу помощи, так как сам ума не приложу, как это сделать.
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
10.01.2017, 18:07
Ответы с готовыми решениями:

Обработка аппаратных прерываний по номеру IRQ
Здравствуйте! Подскажите пожалуйста ответ на вопрос:Как ОС различает когда несколько устройств...

[VM] Реализация аппаратных прерываний
Доброго времени суток, CyberForum. Уже как 2 месяца я пишу свой велосипед - эмулятор платформы...

Глобальные перехваты аппаратных прерываний
Вот посидел попробывал и, понял что вот так нельзя из-под доса отследить или эмулировать нажатия...

Критическая секция запретом аппаратных прерываний
Собственно вопрос в названии. Могу ли я быть абсолютно уверен в том, что код вида: cli .....

8
Модератор
Эксперт по электронике
7487 / 3687 / 1445
Регистрация: 01.02.2015
Сообщений: 11,468
Записей в блоге: 2
11.01.2017, 09:22 2
Лучший ответ Сообщение было отмечено HackSign как решение

Решение

Точно аппаратное прерывание в FreePascal? Не в TurboPascal?

В FPC обработка примерно такая же, но нужно будет переходить в реальный режим. Это несколько сложнее.

Уточните задачу.


Для TurboPascal проверял в DOSBox.
Pascal
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
{$IFNDEF Debug}
{$D-,S-,L-}
{$ENDIF}
{$B-,R-,V-,X+,N+,E-,A-,T-,F-,Q-,P-}
{.$G+}
program SysTimerSample;
 
uses
  CRT;
 
const
  Time1sec = 18;       { 18.2065086 Гц                    }
  Time10sec = 182;     { 1 сутки = 1 573 040 (18 00 B0 h) }
  Time1min = 1092;
  Time1hour = 65543;
  Time24hour = 1573040;
  IntNum = $1C;
var
  TimerDec: word;
 
var
  OldExitProc: Pointer;
  OldIntProc:  Pointer;
 
var
  Sounds: boolean;    {состояние звучания динамика}
 
  VectInt       : Pointer absolute $0000:(IntNum*4  );
  procedure DisableInterrupts; inline($FA); {cli}
  procedure EnableInterrupts;  inline($FB); {sti}
 
  procedure Speaker;
  begin
    Sounds := not Sounds;
    begin
      if Sounds then
      begin
        Sound(440);
        TimerDec := Time1sec * 1;
      end
      else
      begin
        NoSound;
        TimerDec := Time1sec * 4;
      end;
    end;
  end;
{$F+}
  procedure SystemTimer; interrupt;
  assembler;
  asm
    Dec TimerDec
    test TimerDec, 0ffffH
    jnz @@Skip
    call Speaker
  @@Skip:
    pushf
    call  OldIntProc
  end;
 
  procedure DoneSysTimer; far;
  begin
    DisableInterrupts;
    VectInt := OldIntProc;
    EnableInterrupts;
    ExitProc := OldExitProc;
  end;
 
{$F-}
  procedure InitSysTimer;
  begin
    OldIntProc := VectInt;
    DisableInterrupts;
    VectInt := @SystemTimer;
    EnableInterrupts;
    OldExitProc := ExitProc;
    ExitProc := @DoneSysTimer;
  end;
 
begin
  TimerDec:=2;
  Sounds := false;
  InitSysTimer;
  while not KeyPressed do;
  ReadKey;
  NoSound;
end.
Добавлено через 7 минут
Смысл в перехвате пользовательского прерывания от таймера 1Ch. В добавляемом обработчике все действия - декремент одной единственной переменной TimerDec и проверке её на 0. Если равна 0, то вызвать подпрограмму Speaker, в которой или включится или отключится звук, а также будут назначены новые значения переменной TimerDec.

При установке нового прерывания в процедуре InitSysTimer я сразу озаботился о восстановлении исходного вектора прерывания, добавив процедуру DoneSysTimer (восстановление прежнего вектора) в список процедур выхода (которые выполняются при завершении программы). Можно это убрать и восстанавливать вектор вручную в конце программы.

Добавлено через 2 минуты
Почему включение и отключение звука я вынес в отдельную процедуру - там чисто паскалевская обработка с вызовом библиотечных функций (Sound/NoSound). Чтобы не думать о соглашениях о вызове этих процедур.
1
41 / 41 / 36
Регистрация: 23.11.2006
Сообщений: 151
11.01.2017, 10:10  [ТС] 3
Премного благодарен за науку! Теперь понял в каком направлении надобно двигаться. С Ассемблером пока ещё на "Вы" и не приходилось использовать его вставки в программный код языков высокого уровня.
0
538 / 398 / 99
Регистрация: 18.08.2012
Сообщений: 1,024
11.01.2017, 12:52 4
Цитата Сообщение от ФедосеевПавел Посмотреть сообщение
нужно будет переходить в реальный режим
Есть процедуры get_pm_interrupt() и set_pm_interrupt().
Для них имеется специальный тип данных tseginfo.
Кроме того, нужно использовать внешнюю переменную external name '___v2prt0_ds_alias' для инициализации регистра DS в самом обработчике прерываний.
А если программа будет работать не из под ВИНДЫ, то можно обработчик запихнуть непосредственно в IDT.
0
Модератор
Эксперт по электронике
7487 / 3687 / 1445
Регистрация: 01.02.2015
Сообщений: 11,468
Записей в блоге: 2
11.01.2017, 16:32 5
Dmitrinik, я читал в документации FPC, а также в документации TMT Pascal о реализации пользовательских обработчиков аппаратных прерываний при работе в защищённом режиме (под экстендером). Но необходимости подробно изучать у меня не возникало.

Поэтому, если вы это умеете - реализуйте задание топикстартера (ТС) на FPC for DOS. Заодно и пример будет.

Под DOS - т.к. под Windows только драйверы работают с аппаратными прерываниями.

Не по теме:

Я реализовал на TurboPascal потому, что ТС неуверенно пользуется ассемблером, прерываниями в RM, что же говорить о PM. Делаю вывод, что в раздел FreePascal вопрос попал случайно, из-за работы ТС именно в FPC, хотя по программе в учебном заведении изучается TurboPascal.

Вот из последних на сегодня примеров ошибочного размещения
https://www.cyberforum.ru/asm-... 96784.html
Видно, что перед написанием кода я уточнил процессор, но - нет, это - не помогло.

0
Модератор
Эксперт Pascal/DelphiЭксперт NIX
5694 / 3409 / 2430
Регистрация: 22.11.2013
Сообщений: 9,566
Записей в блоге: 1
11.01.2017, 21:25 6
ФедосеевПавел,
строго говоря, в реальном режиме вектор $1C обработчиком аппаратного прерывания не является.
Далее, в отношении обработчика аппаратного прерывания тоже возможны варианты:
1) мы зовем оригинальный обработчик, он сообщит контроллеру о завершении обработки аппаратного прерывания,
2) мы НЕ зовем оригинальный обработчик и сами сообщаем контроллеру о завершении обработки аппаратного прерывания -- помимо управления процессором (CLI/STI), не забываем пообщаться с периферией
Pascal
1
  Port[$20]:=$20;
1
Модератор
Эксперт по электронике
7487 / 3687 / 1445
Регистрация: 01.02.2015
Сообщений: 11,468
Записей в блоге: 2
12.01.2017, 00:04 7
Да, спасибо. Но это уже детали.
Если возвращать управление старому обработчику, то int 08h не отличается от int 1Ch.
Только, если не возвращать - тогда разница проявится.

Не по теме:

Я хотел взять "на слабо" Dmitrinik - поджучивает странными сообщениями, а выдать код под cwsdpmi, обрабатывающий аппаратное (08h) или пользовательское (1Ch) прерывание - сил нет.
Да, видно, насмотрелся канал "Культура" - слишком деликатно сказал, что его сообщение бессмысленное.

1
Эксперт Pascal/Delphi
2359 / 1278 / 1484
Регистрация: 29.08.2014
Сообщений: 4,602
12.01.2017, 12:01 8
извиняюсь за идиотский вопрос fptimer не вариант?
0
Модератор
Эксперт по электронике
7487 / 3687 / 1445
Регистрация: 01.02.2015
Сообщений: 11,468
Записей в блоге: 2
12.01.2017, 19:34 9
Судя по
Цитата Сообщение от HackSign Посмотреть сообщение
Необходимо написать подпрограмму обработки аппаратного прерывания системного таймера
и _GetTickCount в строке 225
Pascal
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
procedure TFPTimerThread.Execute;
var
  SleepTime: Integer;
  S,Last: Cardinal;
  T : TFPCustomTimer;
  
begin
  while Not Terminated do
    begin
    Last := _GetTickCount;
    T:=Timer;
    If Assigned(T) then
      begin
      SleepTime := T.FInterval - (_GetTickCount - Last);
      if SleepTime < 10 then
        SleepTime := 10;
      Repeat  
        S:=5;
        If S>SleepTime then
          S:=SleepTime;
        Sleep(S);
        Dec(Sleeptime,S);
      until (SleepTime<=0) or Terminated;
      T:=Timer;
      If Assigned(T) and not terminated then
        Synchronize(@T.Timer);
      end
    else
      Terminate;  
    end;
end;
Наверное, не подходит.
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
12.01.2017, 19:34

Заказываю контрольные, курсовые, дипломные и любые другие студенческие работы здесь или здесь.

Обработка прерываний
Доброго времени суток. Пытаюсь выполнить пример программы с использованием прерывания, взятый из...

Обработка запросов прерываний
Помогите написать программу для Atmega48 После запуска программы включен светодиод LED5. При...

Обработка запросов прерываний
Добрый день! необходима помощь. 1)Светодиоды загораются, слева направо. 2)После нажатия...

Обработка прерываний таймера
Пытаюсь написать программу, которая перехватывает прерывание таймера и выдает звуковой сигнал...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
9
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2021, vBulletin Solutions, Inc.