Страниц: [1]
  Печать  
Автор Тема: Функция tcdrain()  (Прочитано 7079 раз)
aerial
Участник
*
Offline Offline

Сообщений: 0


Просмотр профиля
« : Января 24, 2005, 11:23:36 am »

Функция tcdrain() некоректно работает. Функция завершает свою работу, когда еще не все байты переданы. Вопрос такой: Как с этим бороться и есть ли другие методы реализации ожидания полной передачи байтов в порт.
PS: есть еще один способ, но мне он неприемлим, потому как по сети я не могу оперировать данным способом.
while ( !(inportb(IObase+5)&0x40) );
где IObase - базовый адресс порта
Записан
kvn
Участник
*
Offline Offline

Сообщений: 1


Просмотр профиля
« Ответ #1 : Января 24, 2005, 12:42:57 pm »

Было у нас то же самое. Боролись именно таким способом.

Может быть, запускать ваш процесс на удаленном узле при помощи утилиты on? В этом случае inp(iobase+5) отработает корректно.
Записан
aerial
Участник
*
Offline Offline

Сообщений: 0


Просмотр профиля
« Ответ #2 : Января 25, 2005, 04:22:16 am »

Да вот хотелось бы обойтись без запуска процессов на удаленном узле
Записан
ed1k
QOR.Moderator
*****
Offline Offline

Сообщений: 739


Просмотр профиля WWW
« Ответ #3 : Января 25, 2005, 05:23:12 am »

Aerial
Да вот хотелось бы обойтись без запуска процессов на удаленном узле

Тогда в зависимости от близости сношений с QSS и толщины кошелька:
1) обратится в QSS или локальному дилеру с просьбой изготовить и продать нормальный драйвер;
2) купить у них DDK/TDK или как оно у них там сейчас называется с исходниками драйвера (а главное библиотеки libio-char) и поправить все самому (там, кстати, есть еще поля непаханные для деятельности, во всяком случае были в релизе 6.1)
3) найти character device DDK от 6.1 (это последний где и библиотека была в исходниках) и поправить все самому (исходники были в свободном доступе на CVS, возможно и сейчас они там же).

Суть правок по сути вопроса - в библиотеке есть файл drain.c с соответствующей функцией, и в драйвере есть такая же функция где-то в tto.c (все названия по памяти, так что может и наврал). Та функция, что в драйвере должна работать как ей и следует, но она никогда не вызывается по понятной причине (если причина непонятна, то пункты 2) и 3) выше вам не подходят).
Записан
ed1k
QOR.Moderator
*****
Offline Offline

Сообщений: 739


Просмотр профиля WWW
« Ответ #4 : Января 25, 2005, 05:27:22 am »

Прошу прощения. Не заметил, что вопрос по QNX4. Но без деталей это все почти также и решается как и написал.
Записан
kvn
Участник
*
Offline Offline

Сообщений: 1


Просмотр профиля
« Ответ #5 : Января 25, 2005, 09:12:51 am »

Боюсь, что в данно конкретном случае не поможет даже толстый кошелек и хорошие отношения с QSSL.

Дело вот в чем. Микросхема UART'а имеет два регистра-передатчика: защелку и сдвиговый. Когда мы делаем вызов write(), данные попадают в регистр-защелку. Далее мы обычно делаем вызов tcdrain(). Из tcdrain()'а мы вываливаемся после того, как драйвер Dev.ser получит прерывание TxRDY (регистр-защелка пуст). В это время сдвиговый регистр еще может передавать данные на ножку Tx порта (у меня этот эффект хорошо проявлялся на низких скоростях - я даже развлекался тем, что одним глазом смотрел на экран монитора, ждал возвращения из ф-ции tcdrain(), а другим - на экран осциллографа, было четко видно, что последний бит уходит с ножки позже, чем завершается tcdrain()). А вот прерывания   по уходу последнего бита с ножки нет. Это - фишка самого чипа, так что Dev.ser здесь, в общем-то, бессилен, поскольку он работает по прерываниям.

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

Для того, чтобы полностью разобраться с этой проблемой, я в свое время вставлял while inp(iobase+5) в исходный текст драйвера Dev.ser (ver 423X), компилил и запускал его. Все работало, но при передаче больших объёмов данных драйвер сжирал все процессорные ресурсы (почему, думаю, ясно).

Мне не понятно, почему вы, Aerial, не хотите запустить процесс удаленно. Если это табу, попробуйте такой вариант.
Запустите на том узле, где по-хорошему должен работать ваш процесс, менеджер, принимающий сообщения типа "адрес порта". Ответом на это сообщение будет сообщение "текущее значение этого порта". Пусть этот менеджер зарегистрирует имя, чтобы его можно было найти по сети. Тогда ваш процесс
после tcdrain() должен делать что-то типа Send(Pid менеджера, &адрес порта, &значение, sizeof, sizeof) в цикле до тех пор, пока (IObase+5)&0x40 не станет равным 0x40.
Но лично я предпочитаю вариант с удаленным запуском.
Записан
aerial
Участник
*
Offline Offline

Сообщений: 0


Просмотр профиля
« Ответ #6 : Января 25, 2005, 11:24:31 am »

Я предполагал если есть функция qnx_ioctl(), с помощью которой можно считать содержимое флагов (IObase+4) на удаленной машине, то может быть, существуют функции с помощью которых можно добраться до содержимого флагов (IObase+5).
В любом случае из прочитанного,ситуация немного прояснилась.
Спасибо вам kvn за содержательный ответ.
Записан
booBot
Участник
*
Offline Offline

Сообщений: 0


Просмотр профиля
« Ответ #7 : Января 25, 2005, 06:37:37 pm »

Эх, склероз!...

Уже не помню как, но мне удалось эмулировать прерывание по выгрузке последнего бита из сдвигового регистра передатчика...
Я, помнится, сыграл на использовании стоп-бита == двум тактам...
(Мне нужно было знать, когда можно переключать двухпроводную линию с передачи на приём.)

Кажется вспомнил - приёмник мог слушать сигнал собственного передатчика, в передатчике был стоп-бит == 2 тактам, а в приёмнике == 1 такту. "Пожиратель эха" и переключал линию.
Да, мой пример не поможет...
Записан
ed1k
QOR.Moderator
*****
Offline Offline

Сообщений: 739


Просмотр профиля WWW
« Ответ #8 : Января 29, 2005, 06:37:28 am »

kvn
На мой взгляд, если бы это прерывание было реализовано в самой микросхеме, то за драйвером дело бы не стало и жить нам было бы немножко легче.

Ну есть же бит в line status register. Только читать его в цикле драйвер не каждый раз должен, а когда приложение вызвало tcdrain(). Драйвер работает не только по прерываниям, потому что с одной стороны у него железо, а с другой приложение работающее с устройтсвом, которое знать ничего не должно про внутренности железа, его прерывания и пр. В двух словах - в Linux с той же микросхемой tcdrain() будет работать как ему и следует. В windows тоже (но там всё называется по-другому). В QNX6 все задумывалось правильно, поэтому, вроде бы, не сложно поправить (может уже и сделали, хотя я не верю). В QNX4 ничего не остается проще, как дописать в qnx_ioctl() вызов драйвера, чтобы возвращался iobase+5 (места там в возвращаемой структуре, вроде, предостаточно) и написать свой tcdrain(). С точки зрения QSS (имея _все_ исходники) возможно, что проще поправить в другом месте. Работы там на пять минут, поэтому повторяю - за большие деньги они вполне могут согласиться.
Записан
Страниц: [1]
  Печать  
 
Перейти в: