Здравствуйте!Возникла необходимость научиться работать с com-портом под Linux.
Мой прошлый опыт в этом направлении, к сожалению, относится к далеким временам лет 15-20 назад. Разработки были под голый DOS и все было проще пареной репы: расчеты/логика на ЯВУ, работа с портами/памятью - inline вставки на ассемблере или отдельно собираемые .obj на том же ассемблере. Продукты с "доведенной" логикой прогоняли под профайлером и пару-тройку самых медленных функций тоже переписывали на ассемблере.
Интернет пестрит статьями по теме, но основная масса, насколько я понимаю, описывает процесс со стороны embedded\ARM и т.п., что мне не очень близко.
Хотелось бы советов от почтеннейшей публики - с чего мне проще начать со своим "багажом", чего остерегаться, на что обратить внимание.
В частности интересны такие вопросы:
1. Если нет особо жестких требований по времени - достаточно ли просто работы с /dev/ttySX, в частности непонятно - можно ли контролировать последовательность приема-передачи (мне важно знать, что такой-то байт был получен до или после отправки такой-то команды)?
2. Правильно ли я понимаю, что вместо того, чтобы расставлять вычисления маленькими кусочками между чтением/записью, сейчас более правильно просто "отсаживать" обмен в отдельный поток с более высоким приоритетом?
3. Важна ли сейчас разница между аппаратными реализациями? Или если ядро распознало устройство и создало в /dev ссылку, то дальнейшие различия несущественны?
4. Значительны ли отличия в работе "классических" портов и преобразователей COM-USB (возможность последних пропадать\появляться мне не важна, важны именно отличия в программировании)?
5. Что можно предпринять во избежание затрат на другие процессы? Пассивная защита (поменьше активных демонов) понятна, а активная?Детали, если они имеют значение: архитектура - i386, скорости мизерные, единицы-десятки байт в секунду, родной софт работает на 2400, 7/1. Оборудование - немецкие промышленные весы времен царя гороха, но прекрасно работающие до сих пор, в отличие от фирмы-продавца.
Надеюсь на ваши советы, заранее благодарен!
Читаешь, записываешь в файл /dev/ttySx, настраиваешь работу с устройством через функцию ioctl.
На мой неискушённый взгляд вот здесь достаточно хорошо изложено:https://www.opennet.ru/docs/RUS/serial_guide/
На хитрые вопросы отвечать не берусь.
Спасибо! Копию текста в другом месте видел, но дата напугала, ушел искать поновее. Оказалось - все вполне неплохо.
> 1. Если нет особо жестких требований по времени - достаточно ли просто
> работы с /dev/ttySX, в частности непонятно - можно ли контролировать последовательность
> приема-передачи (мне важно знать, что такой-то байт был получен до или
> после отправки такой-то команды)?Точная привязка по времени невозможена даже из-за буфера в 16550. В обычном Unix время между приходом байта в порт и чтением из /dev/ttySx никак не регламентировано. Посмотри внимательнее на протокол - если нельзя сделать дисциплину запрос-ответ, то может понадобится какая-нибудь RTOS.
> 2. Правильно ли я понимаю, что вместо того, чтобы расставлять вычисления маленькими
> кусочками между чтением/записью, сейчас более правильно просто "отсаживать" обмен в
> отдельный поток с более высоким приоритетом?Сильно проще - while (select(...)) { read .... write .... }, однако см. #1. Кроме того, read может вернуть только часть посылки и нужно будет дочитывать остальное. Ещё советуют делать tcdrain перед каждой записью.
> 3. Важна ли сейчас разница между аппаратными реализациями? Или если ядро распознало
> устройство и создало в /dev ссылку, то дальнейшие различия несущественны?Именно так.
> 4. Значительны ли отличия в работе "классических" портов и преобразователей COM-USB
> (возможность последних пропадать\появляться мне не важна, важны именно отличия в
> программировании)?ioctl на уровне /dev/ttyU* и /dev/ttyS* не различаются.
> 5. Что можно предпринять во избежание затрат на другие процессы? Пассивная защита
> (поменьше активных демонов) понятна, а активная?На таких скоростях достаточно, чтобы не было свопа. Остальное - мелочи, на которые можно не обращать внимания. Хочется поиграть в нагруженную систему - можно сделать SCHED_FIFO через sched_setscheduler.
>> 1. Если нет особо жестких требований по времени - достаточно ли просто
>> работы с /dev/ttySX, в частности непонятно - можно ли контролировать последовательность
>> приема-передачи (мне важно знать, что такой-то байт был получен до или
>> после отправки такой-то команды)?
> Точная привязка по времени невозможена даже из-за буфера в 16550. В обычном
> Unix время между приходом байта в порт и чтением из /dev/ttySx
> никак не регламентировано. Посмотри внимательнее на протокол - если нельзя сделать
> дисциплину запрос-ответ, то может понадобится какая-нибудь RTOS.Я выразился невнятно. Точная привязка ко времени - не нужна, нужно знать что такой-то ответ пришел после такой-то команды, т.е. порядок ответов относительно команд, а не относительно времени. Железка отвечает за известное время и всегда шестью байтами, если не все нужны, лишние - пустые, первый всегда маркер ответа (не может встречаться в данных). По своей инициативе ничего не присылает, но если долго (около 40 секунд) нет команд, сигналит разрыв.
Родная софтина даже не пытается время измерять (таймер не перехватывает и не программирует), а просто после каждой команды гоняет холостой цикл, и только после этого читает. В связи с этим найти для нее подходящий комп стало хорошим квестом. Из под вайна она работает скверно.
До RTOS, надеюсь, дело не дойдет.
>> 2. Правильно ли я понимаю, что вместо того, чтобы расставлять вычисления маленькими
>> кусочками между чтением/записью, сейчас более правильно просто "отсаживать" обмен в
>> отдельный поток с более высоким приоритетом?
> Сильно проще - while (select(...)) { read .... write .... }, однако
> см. #1. Кроме того, read может вернуть только часть посылки и
> нужно будет дочитывать остальное. Ещё советуют делать tcdrain перед каждой записью.Спасибо, tcdrain и tcflush, похоже - то, что мне нужно. Часть посылки - не страшно, маркерный байт есть, да и перезапросить можно.
>> 3. Важна ли сейчас разница между аппаратными реализациями? Или если ядро распознало
>> устройство и создало в /dev ссылку, то дальнейшие различия несущественны?
> Именно так.
>> 4. Значительны ли отличия в работе "классических" портов и преобразователей COM-USB
>> (возможность последних пропадать\появляться мне не важна, важны именно отличия в
>> программировании)?
> ioctl на уровне /dev/ttyU* и /dev/ttyS* не различаются.Ясно. Я опасался, что нужно при этом следить еще за каким-либо материнским устройством.
>> 5. Что можно предпринять во избежание затрат на другие процессы? Пассивная защита
>> (поменьше активных демонов) понятна, а активная?
> На таких скоростях достаточно, чтобы не было свопа. Остальное - мелочи, на
> которые можно не обращать внимания. Хочется поиграть в нагруженную систему -
> можно сделать SCHED_FIFO через sched_setscheduler.Ясно.
Большое спасибо за ответы!