Таймеры

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

  1. drem1lin

    drem1lin Member

    Публикаций:
    0
    Регистрация:
    17 мар 2009
    Сообщения:
    300
    Доброго времени суток, встала задача ожидания интервала времени в несколько миллисекунд. Какие устройства компа можно использовать для его отсчета? Пока я вспомнил только про HPEТ, но как его прикрутить не очень разобрался, может есть методы проще? Прерывания использовать нельзя, про int 15h я помню.
     
  2. Igor1024

    Igor1024 Васил Троянов Боянов (Azis)

    Публикаций:
    0
    Регистрация:
    15 окт 2010
    Сообщения:
    345
    Адрес:
    Sliven, Bulgaria
    А тот PIT судя по-всему не подходит? Интервал должен быть меньшим? Точно... Этот таймер срабатывает через каждые 0.0549 секунд, а мили - порядка 1/1000.
     
  3. drem1lin

    drem1lin Member

    Публикаций:
    0
    Регистрация:
    17 мар 2009
    Сообщения:
    300
    Грубо говоря мне нужен метод замерить 10 мс
     
  4. FatMoon

    FatMoon New Member

    Публикаций:
    0
    Регистрация:
    28 ноя 2002
    Сообщения:
    954
    Адрес:
    Russia
    Таймер срабатывает через столько, через сколько его запрограммировать. По дефолту 18 раз в секунду, каждые 0.0549 сек. Это максимально возможный интервал (т.е. самый "медленный"). Можно ускорить в 65535 раз :)))
     
  5. Igor1024

    Igor1024 Васил Троянов Боянов (Azis)

    Публикаций:
    0
    Регистрация:
    15 окт 2010
    Сообщения:
    345
    Адрес:
    Sliven, Bulgaria
    Да, а то я смотрю, что в старом железе вместо HPET'a можно PIT юзать для измерения миллисекундных интервалов. Я с ним не работал, и не догадался сразу о его перепрограммировании... Думал дефолтное значение менять нельзя...
     
  6. T800

    T800 Member

    Публикаций:
    0
    Регистрация:
    7 дек 2006
    Сообщения:
    293
    Адрес:
    Moscow
    drem1lin
    Многоуважаемый Pavia где то писал, что out 0x00EB,XX даёт задержку 250 ns (0.25 us = 0.00025 ms).
    Но я не проверял на сколько это соответствует действительности (на разных конфигурациях).
     
  7. MisHel64

    MisHel64 Member

    Публикаций:
    0
    Регистрация:
    9 мар 2011
    Сообщения:
    182
    Не очень понятна фраза, что нельзя использовать прерывания.
    а) Нельзя вызывать прерывания самостоятельно.
    б) Нельзя вешать собственные обработчики прерывания.
    в) Прерывания в системе на момент ожидания запрещены.
    И сразу поясни, про какие прерывания ты говоришь. Аппаратные, типа IRQ, которые мапятся на софтверные, или именно софтверные прерывания.

    В общем я знаю про три варианта.
    1) использовать счетчик циклов процессора. Лично никогда не использую.
    2) Интервальный таймер, с его помощью можно замерить интервалы с точностью до 1/(18.2*256*256), менее 1мкс. Частота счетчика 1.193182МГц. Но для замера больших интервалов требуется довольно сложно объяснимая логика, и/или разрешение IRQ0/INT8
    3) Часы реального времени, где тактование счетчика 1024Гц. IRQ8/INT70h. Но как я не бился, получить 1024 прерывания INT70h в секунду не получается. Тебе не обязательно вешать собственный обработчик, можно обойтись и регистрами состояния.
     
  8. Dmitry_Milk

    Dmitry_Milk Member

    Публикаций:
    0
    Регистрация:
    20 ноя 2007
    Сообщения:
    535
    drem1lin, а мультимедийные таймеры не годятся?
    То есть, функции из mmsystem.dll типа timeGetDevCaps, timeBeginPeriod, SetTimerCallback, timeSetEvent? эти функции специально были разработаны для мультимедийных приложений, работающих с высоким временным разрешением, скажем, порядка требуемых вами миллисекунд.
     
  9. Dmitry_Milk

    Dmitry_Milk Member

    Публикаций:
    0
    Регистрация:
    20 ноя 2007
    Сообщения:
    535
    Отмеривание строго 10 мсек через интервальный таймер вполне легко делается - надо лишь использовать не генерацию меандра (функция 3), а одиночный программный строб (функция 4). В этом режиме после занесения числа таймер однократно отсчитывает до нуля и останавливается, во время счета можно читать состояние.

    1. В порту 61h устанавливаем бит 0 в 1 (включаем подачу импульсов на вход таймера)
    2. В порт 43h заносим значение 0B8h (10_11_100_0b, 2-й канал, двухбайтовый счет, режим 4, двоичный)
    3. В порт 42h заносим младший байт числа (для 10мсек - 9Ch)
    4. В порт 42h заносим старшиый байт числа (для 10мсек - 2Eh)
    5. В цикле ПО ДВА РАЗА читаем порт 42h (первое чтение - младший, второе - старший байт), до тех пор, пока оба не станут нулевыми.

    При необходимости можно воспользоваться и промежуточными значениями счета таймера, о неодновременном чтении младший/старший можно не беспокоиться - в таймере стоит 16-разрядная защелка в момент чтения младшего байта, старший байт уже берется не из счетчика, а из защелки.
     
  10. Dmitry_Milk

    Dmitry_Milk Member

    Публикаций:
    0
    Регистрация:
    20 ноя 2007
    Сообщения:
    535
    Кстати, похожий фокус можно провернуть и с прерыванием таймера IRQ0 - заставить таймер выдать однократное прерывание строго через заданный промежуток времени.
    ТОлько в данном случае надо использовать канал 1 (порт 41h), и управляющее слово будет 78h (01_11_100_0b, 1-й канал, двухбайтовый счет, режим 4, двоичный)
     
  11. Dmitry_Milk

    Dmitry_Milk Member

    Публикаций:
    0
    Регистрация:
    20 ноя 2007
    Сообщения:
    535
    Наврал выше. Не 1-й, 0-й канал для прерывания. Порт 40h и управляющее слово в порт 43h соответственно будет 38h
     
  12. drem1lin

    drem1lin Member

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

    drem1lin Member

    Публикаций:
    0
    Регистрация:
    17 мар 2009
    Сообщения:
    300
    Не годятся, слишком низкий уровень у кода
     
  14. drem1lin

    drem1lin Member

    Публикаций:
    0
    Регистрация:
    17 мар 2009
    Сообщения:
    300
    Спасибо, попробую
     
  15. MisHel64

    MisHel64 Member

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

    Проблема все еще актуальна?
     
  16. MisHel64

    MisHel64 Member

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

    drem1lin Member

    Публикаций:
    0
    Регистрация:
    17 мар 2009
    Сообщения:
    300
     
  18. Dmitry_Milk

    Dmitry_Milk Member

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

    Через пару часов буду дома - проверю.
     
  19. MisHel64

    MisHel64 Member

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

    Так, что пробуй, о результатах доложишь ;)
     
  20. MisHel64

    MisHel64 Member

    Публикаций:
    0
    Регистрация:
    9 мар 2011
    Сообщения:
    182
    Изменяй условия выхода, на что-то типа:
    если прочитанное значение больше ранее прочитанного,
    или прочитанное значение равно нулю, то выход.
    На асме что-то типа:
    @@Loop:
    ....
    in al, XXh
    xchg Ah, Al
    in al, XXh
    xchg Ah, Al
    cmp Ax, Bx
    mov Ax, Bx
    jA @@Exit
    Or Ax, Ax
    jNZ @@Loop
    @@Exit:

    Даже если ты пропустишь переход через НОЛЬ, то у тебя будет 1/18 секунды, что бы это поймать.