Таймеры

Тема в разделе "WASM.OS.DEVEL", создана пользователем drem1lin, 16 май 2011.

  1. FatMoon

    FatMoon New Member

    Публикаций:
    0
    Регистрация:
    28 ноя 2002
    Сообщения:
    954
    Адрес:
    Russia
    При чем тут циклы??? Причем тут "пропустишь"?

    Вам надо: выполнять действие А каждые 10 мс.
    Необходимое условие успеха: действие А должно выполняться менее 10 мс.

    Перепрограммируем таймер на 10 мс кванты времени

    Проверять значение таймера НЕ НАДО - надо перехватить прерывание. И вас будут вызывать автоматом каждые 10 мс. А если больше ничего не требуется, можно и hlt повыполнять.

    Код (Text):
    1. Алгоритм:
    2. 1. Перехватить прерывание от таймера (обычно вектор 08) - переназначить на п.5
    3. 2. настроить таймер на 10 мс.
    4. 3. HLT
    5. 4. JMP 3.
    6.  
    7. 5. Обработчик прерывания - вызывается автоматом, раз в 10 мс.
    8.   Делаем наше действие А. Возвращаемся из прерывания.
     
  2. MisHel64

    MisHel64 Member

    Публикаций:
    0
    Регистрация:
    9 мар 2011
    Сообщения:
    182
    Чтение первого поста, отправляет весь ваш поток сознания в мусорку, и дает исчерпывающие ответы на все поставленные вами вопросы.
     
  3. Dmitry_Milk

    Dmitry_Milk Member

    Публикаций:
    0
    Регистрация:
    20 ноя 2007
    Сообщения:
    535
    Проверил. Инструкции тут не причем, этож отдельная аппаратная вещь.

    В режиме 0 не останавливается на нуле (или останавливается не на нуле), выяснять не стал, лень.
    В режиме 4 ОСТАНАВЛИВАЕТСЯ НА НУЛЕ, через ноль не переходит. Дальше не считает, ноль вы никогда не пропустите, даже если в цикле опроса будет выполняться что-то достаточно длительное.

    Так что, drem1lin, между началом и окончанием исполнения следующего кода проходит 10мсек (ну с точностью до длительности одного цикла опроса счетчика вместе с вашими действиями):
    Код (Text):
    1.     in  al,61h
    2.     or  al,1h
    3.     out 61h,al 
    4.     mov al,0B8h
    5.     out 43h,al
    6.     mov al,09Ch
    7.     out 42h,al
    8.     mov al,02Eh
    9.     out 42h,al
    10. m1:
    11. ;тут можно выполнить какие-либо действия
    12.     in  al,42h
    13.     mov bl,al
    14.     in  al,42h
    15.     mov bh,al
    16.     cmp bx,0
    17.     jnz m1
     
  4. MisHel64

    MisHel64 Member

    Публикаций:
    0
    Регистрация:
    9 мар 2011
    Сообщения:
    182
    Не поленился, написал:

    Код (Text):
    1.     In    Al, 061h        ; {Читаем порт}
    2.     And   Al, 0FCh        ; {Spk & Gate Off}
    3.     Out   061h, Al        ; {Set}
    4.     Mov   Bl, Al          ; {Save}
    5.     Mov   Al, 0B8h        ; {80+30+8}
    6.     Out   043h, Al        ; {Set}
    7.     Mov   Ax, 000FFh      ; {Hi=0 Lo=FF}
    8.     Out   042h, Al        ; {Out Lo}
    9.     XcHg  Ah, Al          ; {Hi=FF Lo=00}
    10.     Out   042h, Al        ; {Out Hi}
    11.  
    12.     Xor   Ax, Ax          ; {=0}
    13.     Mov   Es, Ax          ; {Timer Seg}
    14.     Mov   Di, 0046Ch      ; {Timer Ofs}
    15.     Mov   Dx, Es:[Di]     ; {Timer Val}
    16.     Mov   Cx, 20          ; {Loop Count}
    17.     Mov   Al, Bl          ; {Restore}
    18.     Or    Al, 001h        ; {Gate On}
    19.     Out   061h, Al        ; {START}
    20.   @@Loop:
    21.     In    Al, 042h       ; {Lo}
    22.     XcHg  Ah, Al         ; {Save}
    23.     In    Al, 042h       ; {Hi}
    24.     XcHg  Ah, Al         ; {Swap}
    25.     Or    Ah, Ah         ; {ReLoad?}
    26.     jNZ   @@Ex1          ; {Exit}
    27.     Cmp   Dx, Es:[Di]    ; {Timer Val}
    28.     jE    @@Loop         ; {No Tic}
    29.     Mov   Dx, Es:[Di]    ; {Save New tic}
    30.     Loop  @@Loop         ;
    31.   @@Ex1:
    AH больше нуля на выходе. Где я ошибся?
    Та же картина и при режиме 0
     
  5. drem1lin

    drem1lin Member

    Публикаций:
    0
    Регистрация:
    17 мар 2009
    Сообщения:
    300
    Вообще все описания что я видел, говорят что в 4 он должен остановиться, но что я видел в отладчике утверждает другое, хотя может им просто нельзя смотреть счетчик? завтра попробую запустить код в полевых условиях
     
  6. MisHel64

    MisHel64 Member

    Публикаций:
    0
    Регистрация:
    9 мар 2011
    Сообщения:
    182
    По моей документации, и 0й и 4й переходят через 0, и продолжают счет.
    Код, что я привел, полностью рабочий.
     
  7. Dmitry_Milk

    Dmitry_Milk Member

    Публикаций:
    0
    Регистрация:
    20 ноя 2007
    Сообщения:
    535
    MisHel64, вы меня не поняли

    Зачем вообще обращения к памяти по адресу 0000:046Ch? Я вам говорю про аппаратный счетчик канала динамика (канал 2 таймера), для обращения к нему необходимо всего лишь прочитать порт 42h два раза подряд. Все, ничего больше читать не нужно:
    Код (Text):
    1.   @@Loop:
    2.     In    Al, 042h       ; {Lo}
    3.     XcHg  Ah, Al         ; {Save}
    4.     In    Al, 042h       ; {Hi}
    5.     XcHg  Ah, Al         ; {Swap}
    6.     Or    Ah, Ah         ; {Zero reached?}
    7.     jNZ   @@Loop          ; {If no - continue polling}
     
  8. MisHel64

    MisHel64 Member

    Публикаций:
    0
    Регистрация:
    9 мар 2011
    Сообщения:
    182
    Я то тебя отлично понял, а вот ты меня нет. Я выслушал твое мнение, и решил его проверить.
    И по этому то же решил написать небольшой кусок кода, что бы проверить справедливость твоих утверждений, об остановке счета.
    Выход по условию AX=0, уже в моем тестовом коде не применим. Так как не зависимо от того, продолжает счетчик считать после достижения нуля, или продолжает счет с переходом через ноль, такое условие сработает, и по этому код не даст ответа на поставленный мной вопрос.
    Для этого и был организован дополнительный цикл ожидания, и я посчитал простейшим способом для этого использовать счетчик тиков.

    И вот результат моего эксперимента показал, что счетчик переходит через ноль, и продолжает счет, что полностью совпадает с документацией, которой пользуюсь я.

    В дальнейшем, при проектировании уже реального, а не тестового кода, стоит предусматривать ситуацию, что может произойти переход через ноль, с продолжением счета, и тот момент, что факт перехода через ноль может быть пропущен.

    PS: Так как данная задача для меня то же сейчас актуальна, и пока носит академический характер, просил бы вас запустить мой код на своем железе, в том числе и под виртуальными машинами, и сообщить результат.
     
  9. Dmitry_Milk

    Dmitry_Milk Member

    Публикаций:
    0
    Регистрация:
    20 ноя 2007
    Сообщения:
    535
    Ясно, но тогда непонятно, каким образом вы проверяете.
    Код (Text):
    1. @@Loop:
    2.     In  Al, 042h       ; {Lo}
    3.     XcHg    Ah, Al         ; {Save}
    4.     In  Al, 042h       ; {Hi}
    5.     XcHg    Ah, Al         ; {Swap}
    6.     Or  Ah, Ah         ; {ReLoad?}
    7.     jNZ @@Ex1          ; {Exit}
    - это же ведь идет сразу после запуска счетчика. Конечно же после запуска в нем еще какое-то промежуточное ненулевое значение (счетчик же еще не успел досчитать до нуля!), вы читаете это ненулевое значение и тут же выходите (СОВСЕМ ВЫХОДИТЕ!), и конечно же видите в AX прочинанное ненулевое значение. Счетчик просто еще ни разу не дошел до нуля, а вы делаете вывод, что он не остановился на нуле.

    Я проверял просто запуская скомпилированный для DOS exe-шник под WinXP, то есть в ntvdm. Я не знаю подробностей работы vdm, возможно она полностью эмулирует (с остановом на нуле в режиме 4) работу счетчиков, а не дает работать с реальной аппаратурой. Программа инициализировала счетчик, дальше в указанном мною цикле отслеживала достижение счетчиком нуля, затем выходила из цикла и ожидала нажатия клавиши, после чего снова проверяла значение счетчика, оно оставалось нулевым.

    Сначала давайте разберемся с логикой вашего кода, мои претензии к определению факта неостанова в нуле написаны выше.
     
  10. MisHel64

    MisHel64 Member

    Публикаций:
    0
    Регистрация:
    9 мар 2011
    Сообщения:
    182
    Внимательнее код читать нужно!

    Эта проверка, а не перешел ли счетчик через ноль, и не продолжил ли счет.

    В старшем байте НУЛЕВОЕ. Посмотрите, какое значения я в него записываю.

    Я выхожу при не нулевом AH, а не AX. А в AH ненулевое значение будет только, если счетчик плодожил счет после перехода через ноль.

    А я на реальном железе.

    Вроде на все ваши претензии ответил? Причина их возникновения, это, только ваша невнимательность.
     
  11. Dmitry_Milk

    Dmitry_Milk Member

    Публикаций:
    0
    Регистрация:
    20 ноя 2007
    Сообщения:
    535
    Виноват. Дурак. Действительно весь ваш код не имел для меня смысла из-за того, что я видел AX там, где фактически написано AH :dntknw: Хотя в ваш огород тоже камень есть - пишите прозрачнее, зачем было запутывать двумя xchg (фактически полное заполнение AX двумя последовательными чтениями), когда нагляднее было сохранить первый раз в другом 8-битном регистре, не вы один ваш код читаете :)

    Но вот тогда непонятное расхождение, почему в ntvdm останов в нуле все-таки произошел, неужели полная программная эмуляция этой аппаратуры, да еще и неточно соответствующая?
     
  12. Dmitry_Milk

    Dmitry_Milk Member

    Публикаций:
    0
    Регистрация:
    20 ноя 2007
    Сообщения:
    535
    Блин, опять невнимательносьть :dntknw:

    Нагляднее было бы вообще первое чтение сделать холостым, раз al не используется. Просто два in al,42h подряд и проверять or al,al :)
     
  13. Dmitry_Milk

    Dmitry_Milk Member

    Публикаций:
    0
    Регистрация:
    20 ноя 2007
    Сообщения:
    535
    Да, кстати, раз такая пьянка, проверить бы еще и режимы счета с загрузкой/чтением только одним младшим байтом и только одним старшим (то есть, конфигурации 98h и 0A8h).
     
  14. gaeprust

    gaeprust New Member

    Публикаций:
    0
    Регистрация:
    2 май 2011
    Сообщения:
    188
    drem1lin
    Вам верно сказали, PIT решит все ваши проблемы. И прерывания тут не причём.
     
  15. drem1lin

    drem1lin Member

    Публикаций:
    0
    Регистрация:
    17 мар 2009
    Сообщения:
    300
    Я потестировал, в принципе все работает нормально, счетчик в 0 останавливается. Так что решение найдено, всем спасибо. Если кому надо могу выложить код.
     
  16. Dmitry_Milk

    Dmitry_Milk Member

    Публикаций:
    0
    Регистрация:
    20 ноя 2007
    Сообщения:
    535
    MisHel64, запустил ваш код (тоже в ntvdm) - остановилось на нуле (то есть, выхода по JNZ не было, завершилось окончанием loop)! Либо действительно ntvdm эмулирует режим 4 с остановом в нуле, либо еще хуже - на разных матерях разная реализация.
     
  17. Dmitry_Milk

    Dmitry_Milk Member

    Публикаций:
    0
    Регистрация:
    20 ноя 2007
    Сообщения:
    535
    Подождите радоваться. Один и тот же код, написанный MisHel64, по-разному отработал в разных ситуациях. У него (чисто аппаратно) - не остановился, у меня в ntvdm - остановился.
     
  18. drem1lin

    drem1lin Member

    Публикаций:
    0
    Регистрация:
    17 мар 2009
    Сообщения:
    300
    Я запускал на реальном железе, он остановился. Хотя разобраться конечно стоит, почему у MisHel64 он не остановился
     
  19. MisHel64

    MisHel64 Member

    Публикаций:
    0
    Регистрация:
    9 мар 2011
    Сообщения:
    182
    Ты запускал на реальном железе, без всяких эмуляторов? В голом DOSе?
     
  20. FatMoon

    FatMoon New Member

    Публикаций:
    0
    Регистрация:
    28 ноя 2002
    Сообщения:
    954
    Адрес:
    Russia
    Для общего развития, озвучте область задач, в которой требуется однократная задержка в 10 мс? Все, что приходит в голову - периодические действия. Для периодических логичнее все равно основной канал и прерывание, чем с циклами и ожиданием. Тем более если решается в голом ДОСе