Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Точность измерения временных интервалов для UART в windows


Страницы:   1 2 3

vertal ©   (2006-12-24 17:20:00) 

По com-порту отправляю сообщение (WriteFile). Жду завершения его отправки через FlushFileBuffers. Пытаюсь принять ответ, состоящий из символов. Признаком конца сообщения-ответа служит отсутствие прибытия  нового символа после предыдущего в течение более 4 милисекунд. Максимальная длина ответа - 256 символов. Осуществляется это все как:

 PurgeComm(fPort, PURGE_RXCLEAR);
 OpResult = WriteFile(fPort, Msg, cnt, &Garbage, NULL);
 FlushFileBuffers(fPort);
 OpResult = ReadFile(fPort, OutBuf, 257, &ActualRead, NULL);

Для того, чтобы после 4 милисекунд отсутствия символов на линнии ReadFile вернула то, что было прочитано, предварительно вызываю SetCommTimeouts, со значением 4 в  ReadIntervalTimeout. Проблема в том, что при таких условиях _иногда_ (через раз примерно) прием сообщения-ответа прекращался на середине. То есть я предполагаю, что это из-за неточности измерения таких промежутков времени windows или стандартными драйверами. После установки ReadIntervalTimeout в значение 16 (8 не помогло) сбои исчезли. Сталкивался ли кто-нибудь с подобным? Или что-то не так в приведенном коде?


kaZaNoVa   (2007-01-03 21:32:00) [21]

tesseract ©   (03.01.07 21:27) [20]
даже при критическом приоритете как процесаа так и потока?


tesseract   (2007-01-03 21:27:00) [22]


> kaZaNoVa ©   (03.01.07 11:19) [15]
> RayGun ©   (03.01.07 10:59) [14] Тогда таймаут можно организовать
> в цикле, вызывая ReadFile и QueryPerformanceCounter, и проверяя,
>  пришли ли данные или истек таймаут, но такой поток будет
> "кушать" процессорное время, причем довольно сильно. И опять
> же, ничего не мешает Windows отобрать у потока в середине
> данного цикла процессорное время на те же 10 мс.контролировать
> можно в отдельном потоке с критическим приоритетом и sleep(1)
> для снятия нагрузки на систему)


Проще написать драйвер. Так 16 мс не выловишь.


С   (2007-01-03 21:19:00) [23]

>vertal ©   (03.01.07 19:57) [18]

Попробуйте так:
ReadIntervalTimeout = 4
ReadTotalTimeoutMultiplier = 0
ReadTotalTimeoutConstant = 0

Моожет статься, это даст дополнительную пищу для размышлений.


vertal   (2007-01-03 19:57:00) [24]


> Германн ©   (03.01.07 02:40) [9]
> Готов обсудить! Гарантирую, моё буферное устройство, твои
> запросы полностью удовлетворит!

Да я верю. Мы и сами можем такое сделать. Вопрос в целесообразности. Эта программа для PC, которую я сейчас пишу, будет тестовой программой, позволяющей проверять работоспособность наших контроллеров. Поставлять вместе с ней еще какое-то дополнительное устройство - будет слишком жирно.
RayGun ©   (03.01.07 09:58) [10]
Как я понял, в данном случае протокол обмена построен по принципу Master/Slave: компутер (Master) посылает запрос, а подключаемое устройство (Slave) должно ответить на него не более чем через 4 мс.
Да, Master-Slave, да сейчас компьютер выспутает в роли мастера. Подключаемое устройство должно ответить за некий разумный интервал (сейчас поставлено 80 мс), а idle line > 4 мс - (при baud rate 9600 бит/с это и есть 3,5 символа) это признак конца сообщения.
Если не очень критично, то почему бы просто не установить таймаут побольше (например, 20 мс)?
Да можно. Так видимо и останется. Прсто хочется понять причину такого поведения системы.

> С   (03.01.07 10:20) [11]
> >vertal ©А как у Вас установлены остальные члены COMMTIMEOUTS?
>

Вопрос конечно по теме. Сейчас
ReadIntervalTimeout = 4 (работает через раз) или 16 (работает всегда)
ReadTotalTimeoutMultiplier = 0
ReadTotalTimeoutConstant = 80
Для приведенного кода еще критично, чтобы FlushFileBuffers возвращала управление только после того, как буфер действительно будет очищен. Судя по описанию, она так и должна поступать.

Организовывать цикл приема символов - на мой взгляд извращение, и к тому же не гарантирует от переключения потоков во время его выполнения.

Я пробовал повышать приоритет потока, работающего с портом. Не заметил разницы в частоте возникновения сбоев.


Anatoly Podgoretsky ©   (03.01.07 15:34) [17]
Только REAL TIME OS, подходят ДОС и однозадачные микроконтроллеры.

Видимо да.


Anatoly Podgoretsky   (2007-01-03 15:34:00) [25]

> RayGun  (03.01.2007 11:31:16)  [16]

Только REAL TIME OS, подходят ДОС и однозадачные микроконтроллеры.


RayGun   (2007-01-03 11:31:00) [26]

> kaZaNoVa ©   (03.01.07 11:19) [15]

Да, наверное, так будет проще, чем с мультимедийным таймером и событиями


kaZaNoVa   (2007-01-03 11:19:00) [27]

RayGun ©   (03.01.07 10:59) [14]
Тогда таймаут можно организовать в цикле, вызывая ReadFile и QueryPerformanceCounter, и проверяя, пришли ли данные или истек таймаут, но такой поток будет "кушать" процессорное время, причем довольно сильно. И опять же, ничего не мешает Windows отобрать у потока в середине данного цикла процессорное время на те же 10 мс.


контролировать можно в отдельном потоке с критическим приоритетом и sleep(1) для снятия нагрузки на систему)


RayGun   (2007-01-03 10:59:00) [28]

> kaZaNoVa ©   (03.01.07 10:51) [13]

Измерять интервалы будет точно, но делу поможет только в том случае, если ReadFile будет использоваться в асинхронном режиме, т.е. сразу после вызова возвращать управление, не зависимо от того, приняты данные или нет. Тогда таймаут можно организовать в цикле, вызывая ReadFile и QueryPerformanceCounter, и проверяя, пришли ли данные или истек таймаут, но такой поток будет "кушать" процессорное время, причем довольно сильно. И опять же, ничего не мешает Windows отобрать у потока в середине данного цикла процессорное время на те же 10 мс.


kaZaNoVa   (2007-01-03 10:51:00) [29]

 
Var k, h:int64;
QueryPerformanceFrequency(h);
QueryPerformanceCounter(k);


RayGun   (2007-01-03 10:41:00) [30]

> vertal ©   (03.01.07 00:01) [8]
> Что мне не нравится - если ReadFile действительно проверяет эти таймауты по предположенному алгоритму, то даже их увеличение не гарантирует от такого рода ошибок - если система очень занята например.

Чтобы минимизировать такого рода ошибки, можно поднять приоритет процессу или потоку до TimeCritical, тогда больше вероятности, что ваше приложение получит свой квант времени и прочитает данные, принятые драйвером, даже при большой загрузке системы.


С   (2007-01-03 10:20:00) [31]

>vertal ©

А как у Вас установлены остальные члены COMMTIMEOUTS?


RayGun   (2007-01-03 09:58:00) [32]

> С   (02.01.07 15:46) [7]
> Не обижайтесь, но я считаю неверным сам подход - закладываться на таймаут как признак конца передачи.

Подход, конечно, не годится для не real-time OS, но используется в некоторых промышленных стандартах на протоколы обмена (например, ModBus RTU, где между пакетами выдерживаются паузы продолжительностью 3,5 от времени передачи одного байта). Чтобы такие протоколы работали под Windows, разработчики, как правило, увеличивают таймауты до значений, кратных кванту Windows (что, конечно, криво и неправильно, но работает). Как я понял, в данном случае протокол обмена построен по принципу Master/Slave: компутер (Master) посылает запрос, а подключаемое устройство (Slave) должно ответить на него не более чем через 4 мс. Если не очень критично, то почему бы просто не установить таймаут побольше (например, 20 мс)?


Германн   (2007-01-03 02:40:00) [33]


> то выхода видится два - собственный драйвер UART или, что
> предпочтительнее, буферное устройство

Готов обсудить! Гарантирую, моё буферное устройство, твои запросы полностью удовлетворит!


vertal   (2007-01-03 00:01:00) [34]

> С   (02.01.07 15:46) [7]</a>
Похоже, что дело обстоит так, как вы описали. Я считаю, что раз в справке по WinAPI пишут, что интервалы задаются в мс, то и делали бы разработчики Windows стандартный драйвер, способный всегда, а не через раз корректно обрабатывать такие параметры.
Не обижайтесь, но я считаю неверным сам подход - закладываться на таймаут как признак конца передачи.
Устройство должно реализовывать некий стандартный протокол (ModBus/RTU), где как раз idle line в течение (4 мс) служит признаком конца сообщения, я не могу этот протокол менять.
то выхода видится два - собственный драйвер UART или, что предпочтительнее, буферное устройство
Написание драйвера я за примемлемое время не потяну, остановился просто на варианте с увеличенными таймаутами. Что мне не нравится - если ReadFile действительно проверяет эти таймауты по предположенному алгоритму, то даже их увеличение не гарантирует от такого рода ошибок - если система очень занята например.


С   (2007-01-02 15:46:00) [35]

Исходя из симптомов можно предположить следующее:

Во время интервала ожидания некий сторонний поток запросил процессорное время и, естественно получил его в размере 10 МСек. После этого управление вернулось Вашему потоку. Так как с момента вызова ReadFile времени прошло больше, чем было Вами установлено в качестве таймаута, то произошел возврат из функции по таймауту. Видимо, система проверяет таймаут до того, как проверит состояние буфера приема UART. Можно рассуждать, логично ли делать так, но вряд ли это имеет смысл. Я, например, считаю, что так поступать правильно, кто-то со мной не согласится. Но факт есть факт - разработчики сделали так, а не иначе.

Не обижайтесь, но я считаю неверным сам подход - закладываться на таймаут как признак конца передачи. Таймаут можно использовать как признак выхода устройства из строя, установив его разумным, но никак не признак окончания передачи. Наилучшим на мой взгляд вариантом будет переделка протокола. Можно, например, передавать размер пакета или определить символ-признак конца. Это будет стандартным, апробированным и надежным решением. Если это почему-либо не подходит, то выхода видится два - собственный драйвер UART или, что предпочтительнее, буферное устройство, которое будет "приводить" протокол обмена к нормальному для Windows виду.


vertal   (2007-01-02 15:09:00) [36]

Системные часы тикают с интервалом в 10 мс.
Но по моим представлениям, отсчет временных интервалов для символов с UART должен осуществляться на более низком уровне, чем thread sheduling, и величина этого кванта и переключение потоков не должны влиять на его точность. Мне не нужен именно таймер высокой точности, мне нужно чтобы система определяла времена прихода символов по UART с точностью едеиницы мс. В справке нет никаких комментариев по поводу точности выдерживания параметров из _COMMTIMEOUTS, которые задаются в мс. Смотрели на осциллографе - в самом приходящем сообщении нет таких пауз. Такое поведение наблюдается на двух системах - 2000 и XP.


tesseract   (2007-01-02 13:59:00) [37]

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


RayGun   (2007-01-02 13:33:00) [38]

Более-менее приемлемую точность (1-2 мс) может обеспечить multimedia timer (TimeGetDevCaps, TimeBeginPeriod, TimeSetEvent), но может не работать в версиях   Windows ниже NT4.0


RayGun   (2007-01-02 13:16:00) [39]

> Anatoly Podgoretsky ©   (02.01.07 12:15) [2]

Разные, да, но по умолчанию вроде 10-16 мс, или не так?


Anatoly Podgoretsky   (2007-01-02 12:15:00) [40]

> RayGun  (02.01.2007 12:05:01)  [1]

квантs времени Windows они разные, но только не 16 мс


Страницы:   1 2 3

Наверх

Титульная страница Поиск, карта сайта Написать письмо