Формирование задержки

Тема в разделе "WASM.WIN32", создана пользователем AB_Celitel, 21 июл 2006.

  1. AB_Celitel

    AB_Celitel New Member

    Публикаций:
    0
    Регистрация:
    9 июл 2005
    Сообщения:
    72
    Адрес:
    Россия, г.Иваново
    Приветствую всех!
    Такая проблема, как программным путем можно организовать задержку 10мкс?
    Можно конечно использовать системный таймер, но для этого требуется вызвать
    прерывание BIOS int 15h с ф-цией 86h, что возможно только из доса.
    А надо чтоб это все работало под виндой (желательно WIN 9X)
    Заранее спасибо
     
  2. Chingachguk

    Chingachguk New Member

    Публикаций:
    0
    Регистрация:
    2 сен 2002
    Сообщения:
    340
    В 9x системный таймер работает с периодом ~600 мкс, а int 15h, как ты сам заметил, отрабатывает неверно (сразу возвращается). GetTickCount тупо возвращает глобальный счетчик по этим самым 600 мкс.

    Так что "стандартно", пожалуй, никак. Возможно провести калибровочные измерения выполнения десятка mov eax,eax или типа in al,_ненужный порт_ (in/out работает дольше), выполнять их в драйвере (динамический VxD), обрамленные cli/sti (хотя cli в win32 вроде в 9x тоже работает как-то).

    Тебе в VxD это нужно или в win32?
     
  3. asmfan

    asmfan New Member

    Публикаций:
    0
    Регистрация:
    10 июл 2006
    Сообщения:
    1.004
    Адрес:
    Abaddon
    QueryPerformanceCounter
    QueryPerformanceFrequency
    Sleep
    rdtsc
    Different multimedia timers...
    Regards
     
  4. AB_Celitel

    AB_Celitel New Member

    Публикаций:
    0
    Регистрация:
    9 июл 2005
    Сообщения:
    72
    Адрес:
    Россия, г.Иваново
    Chingachguk
    Мне это нужно в win98, но без драйверов. ( хотелось бы, но если без драйвера VxD никак, то с ним )

    asmfan
    Все эти ф-ции вроде как не могут делать задержку меньше 1 мс, а нужно 10 мкс.
     
  5. Ustus

    Ustus New Member

    Публикаций:
    0
    Регистрация:
    8 авг 2005
    Сообщения:
    834
    Адрес:
    Харьков
    AB_Celitel
    Из QueryPerformanceFrequency получаем частоту счетчика. На моей рабочей железяке это 3014530000, т. е. похоже, что это частота проца и используется rdtsc.
    Из QueryPerformanceCounter получаем текущее значение счетчика. По идее можно получить задержки значительно меньше 10 мкс, но врядли очень точно.
     
  6. AB_Celitel

    AB_Celitel New Member

    Публикаций:
    0
    Регистрация:
    9 июл 2005
    Сообщения:
    72
    Адрес:
    Россия, г.Иваново
    Ustus

    Т.е. если к примеру запомнить текущее значение счетчика с помощью QueryPerformanceCounter, а затем в цикле снова получать текущее значение и сравнивать с сохраненным до тех пор пока разница между ними не составит 10.
    Так что ли?
     
  7. asmfan

    asmfan New Member

    Публикаций:
    0
    Регистрация:
    10 июл 2006
    Сообщения:
    1.004
    Адрес:
    Abaddon
    Ты знаешь частоту счетчика (резолюшн; мелкость разбиения; разрешение) за 1 секунду, ты знаешь сам счетчик... Так почему бы тебе не организовать всё это воедино...?
    Чти МСДН, учи мат.часть:)©подполковник Шведов...
     
  8. ECk

    ECk Member

    Публикаций:
    0
    Регистрация:
    9 апр 2004
    Сообщения:
    454
    Адрес:
    Russia
    1. Сними значение rdtsc
    2. Вызови Sleep(1)
    3. Сними значение rdtsc
    Разность между значениями "после" и "до" вызова rdtsc считай равной количеству тактов за 1 миллисекунду (лучше повторить несколько раз и аппроксимировать на случай возможных DPC, APC и прочего).
    Потом делай cli, в ecx клади количество тактов на нужное число микросекунд и выполняй команду в цикле (между регистрами например погоняй что-нибудь). А потом sti есессено не забудь вызвать.
    Должно по идее получиться (чем больше количество тестовых шагов 1,2,3 повторишь, тем точнее будет)
     
  9. Pavia

    Pavia Well-Known Member

    Публикаций:
    0
    Регистрация:
    17 июн 2003
    Сообщения:
    2.409
    Адрес:
    Fryazino
    Ustus
    QueryPerformanceFrequency выберает самый быстрый мультимедиа таймер. Всего разновидностей 3 штуки. Наиболее распростроненная частота 3579545.
     
  10. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    Кто в лес, кто по дрова ;))
    ECk
    Ес-но никаких Sleep с "бесконечными" повторами не нужно - для это существует QueryPerformanceFrequency
    Pavia
    QueryPerformanceFrequency выдает число тактов процессора за 1 сек. Т.е. по сути тоже самое, о чем говорит ECk, только за секунду и вычисляется это значение один раз при старте винды. Разумеется это число зависит от частоты CPU, поэтому не понятно о каких "разновидностях" и "наиболее распространенных" значениях может идти речь ;)
    А QueryPerformanceCounter это по сути та же rdtsc плюс фиксированное смещение. В отличие от обычного rdtsc, Query.. выполняется в ядре, поэтому с одной стороны на нее не действуют запреты TSD = 1, а с другой стороны уходит больше времени на вызовы\возвраты
     
  11. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    Мдя, прошу прощения, к Win 9x вышеприведенные измышления не относятся
    Видимо в 9х (а может и в ранних NT, теперь уж и не знаю :) и в самом деле QueryXXX по таймеру работает
     
  12. Pavia

    Pavia Well-Known Member

    Публикаций:
    0
    Регистрация:
    17 июн 2003
    Сообщения:
    2.409
    Адрес:
    Fryazino
    leo
    И какая у меня частота процессора если QueryPerformanceFrequency вернул 3579545, у друга такаяже, а комп совершенно другой. Найду статью покажу откуда вычитал, не нашел. Да в некоторых системах используется RDTSC.
     
  13. AB_Celitel

    AB_Celitel New Member

    Публикаций:
    0
    Регистрация:
    9 июл 2005
    Сообщения:
    72
    Адрес:
    Россия, г.Иваново
    Извините за глупый вопрос, а что такое RDTSC? :)))
     
  14. AB_Celitel

    AB_Celitel New Member

    Публикаций:
    0
    Регистрация:
    9 июл 2005
    Сообщения:
    72
    Адрес:
    Россия, г.Иваново
    Ну может что бы более понятно было для чего это все требуется :
    Я пишу прогу для управления своим программатором контроллеров, а для прошивки 87C51 и аналогичных требуется на определенную лапу посылать 25 импульсов длиной 100мкс с интервалом 10мкс. Вот в этом и вся проблема. Может теперь найдутся еще какие-либо решения данной задачи.
    Заранее спасибо.

    P.S.
    ECk
    Ты имеешь ввиду, что когда мы узнаем кол-во тактов за 1мс, то мы их разделим на 1000
    что бы узнать кол-во тактов за 1мкс, а в ecx положим кол-во тактов за 1мкс * на кол-во микросекунд при условии что цикл будет выполнятся примерно за 1 такт. И после этого всего получим нужную задержку. Я так понял?
     
  15. Quantum

    Quantum Паладин дзена

    Публикаций:
    0
    Регистрация:
    6 янв 2003
    Сообщения:
    3.143
    Адрес:
    Ukraine
    AB_Celitel
    Микроинструкция такая.

    Это же через COM порт посылается, так? Тогда зачем самому задавать задержки, если это может сделать контроллер порта (UART)? Достаточно настроить baudrate под эти задержки и отправить цепочку байт.
     
  16. AB_Celitel

    AB_Celitel New Member

    Публикаций:
    0
    Регистрация:
    9 июл 2005
    Сообщения:
    72
    Адрес:
    Россия, г.Иваново
    Quantum
    Дело в том, что программатор подключен через LPT порт. А сам программатор состоит из 3-х параллельных 8-разрядных регистра (для младшего байта адреса, старшего байта адреса и байта данных) и управляющего счетчика который эти регистры поочередно переключает на запись. Импульсы на управляющий счетчик, а также на ключ который подает напряжение записи и ключ который подает эти короткие импульсы(100мкс) подаются напрямую с LPT порта, т.о. комп полностью управляет программатором.
     
  17. Quantum

    Quantum Паладин дзена

    Публикаций:
    0
    Регистрация:
    6 янв 2003
    Сообщения:
    3.143
    Адрес:
    Ukraine
    AB_Celitel
    Организовать задержку 10мкс в винде невозможно. Нужно либо менять ось, либо менять интерфейс ПК <-> программатор (добавить самопальный генератор этих самых импульсов по сигналу с компа). Я бы выбрал второе.
     
  18. drmad

    drmad New Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    332
    Адрес:
    Russia
    Quantum

    Достаточно настроить baudrate под эти задержки и отправить цепочку байт

    А требуемую скважность как обеспечить?

    Chingachguk

    В 9x системный таймер работает с периодом ~600 мкс,

    Я дико извиняюсь, но AFAIK, это не так. Я много раз на разных машинах в разных системах разными способами измерял эту величину. Во-первых, она непостоянна и, вроде бы, управляется timeBeginPeriod-ом. Во-вторых, по умолчанию, сразу после старта Маздая она тоже не 600 мкс. Откуда взялась эта цифра? Доказательства предоставить можно?

    AB_Celitel

    1. QueryPerformanceConter / QueryPerformanceFrequency.
    2. RDTSC
    3. Сканирование счетчика 2-го ("музыкального") канала таймера.
    4. Калиброванный цикл (т.е. взять, например, цикл из 1000000 итераций, точно измерить его длительность при помощи (1), (2) или (3), а потом в нужное количество раз уменьшить).

    По собственному опыту - у (1) и (3) большеватые накладные расходы, по крайней мере несколько мкс. Т.е. использовать можно, но константы придется подбирать, глядя в осциллограф, впрочем, это любых методов касается. И еще, самое главное: совсем побороть многозадачность Маздая не получится, т.е. рано или поздно произойдет переключение на другие потоки и получится большая задержка. Поэтому можно попробовать дать рабочему потоку TIME_CRITICAL_PRIORITY, это не спасет от переключения на другие потоки, но отсрочит на 4-5 секунд, вполне должно хватить на передачу требуемой серии импульсов.
     
  19. Quantum

    Quantum Паладин дзена

    Публикаций:
    0
    Регистрация:
    6 янв 2003
    Сообщения:
    3.143
    Адрес:
    Ukraine
    drmad
    А в чём проблема?

    По условию нужно выдать 25 таких импульсов:
    Код (Text):
    1.     100us  10us
    2. __|''''''''|__|''''''''|__|''''''''|
    Получается такая последовательность: 011111111110111111111101111111111 и т.д.

    Настраиваем скорость так чтобы каждый бит имел длительность 10мкс. Размер байта задаём 8 бит, + 1 бит чётности + 1 stop bit. Итого, получаем 10 единиц и 1 нолик (start bit) в каждом периоде.
     
  20. Chingachguk

    Chingachguk New Member

    Публикаций:
    0
    Регистрация:
    2 сен 2002
    Сообщения:
    340
    drmad

    Да чего там дико извиняться ;) Я тоже мог быть не прав: я измерял это так. Года 4 назад я улучшал быстродействие брутфорса md5+rc4 (excel), на компе P120 МГц, win98. Измерения делал с помощью SoftIce ;), у него собственное мертвое время было ~60 мкс. Я обнаружил, что функа GetTickCount читает некую глобальную ячейку, которую обновляет некая подпрограмма в ядре, которую вызывает (вроде бы!) обработчик таймера, и вызовы были как раз 1 раз в ~600мкс...

    Возможно, оно и регулируется виндой в зависимости от скорости CPU (интересно, из каких соображений ?...), и на более мощном компе винда его сделат поменьше...

    ++

    По проблеме. Имхо, такие задержки _ТОЧНО_ нельзя делать даже на самом быстром на сей момент компе в _win_. Да, можно добиться что в некотором небольшом периоде (секунда? три? more?) все будет "гладко", но _никто_ не будет четко передавать управление коду который посылает данные с требуемой частотой... Решение, ИМХО, лежит в написании динамического VxD, который нафик блокирует все, прерывания все остальные, переделывает таймер на нормальную частоту / использует калибровки под частоту CPU и делает требуемые действия, затем все гладко возвращается на обычную винду... Разве что часики некорретные будут...