LINUX.ORG.RU

флаш дескриптора последовательного порта.

 


0

1

Добрый день всем. В общем, имеется последовательный порт (на ft232), по нему идет обмен. В силу извращений с протоколом, которые сделал вендор необходимо запилить следующий флоу.

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

В общем, код, местами кривоватый, ибо постоянно экспериментирую с протоколом разными хаками, тут: https://github.com/nekromant/stcdude

И вот тут начинается самое интересное. Оказывается, write сливает данные в какой-то кеш. И закрытие дескриптора порта приводит к тому, что на логическом анализаторе виден только маленький кусок отправленных данных. fsync, tcdrain тут так же не спасают, ровно как и разные O_SYNC/O_DSYNC при открытии. Если дескриптор не закрывать, а просто поменять скорость, то последняя посылка отправляется частично на новой скорости. Единственный хак который дал рабочий вариант -

	char* packet = pack_payload(tmp, len, HOST2MCU);
	write(us->fd, packet, PACKED_SIZE(len));
	usleep(200000); /* FixMe: Find a better way to flush the data */
Но как очевидно, это не тру, не метально круто, не замогильно ужасно и вообще быдлорешение. Есть у кого какие идеи?

★★★★★

Возможно я ошибаюсь, но fflush не поможет?

Gregon ()
Ответ на: комментарий от greek_31

Нет, direct еще не пробовал, приеду в мск к макету и попробую к O_SYNC добавить O_DIRECT.

AiFiLTr0 ★★★★★ ()
Ответ на: комментарий от AiFiLTr0

> tcdrain не помогает, первое что я попробовал.

какой размер аппаратного буфера? либо подожди после tcdrain некоторое время (можно рассчитать из текущего баудрейта и размера буфера), либо перед tcdrain выплюнь мусор размером с аппаратный буфер.

arsi ★★★★★ ()
Ответ на: комментарий от arsi

Мусор выплюнуть не могу, у мк крыша съедет. У ft232 FIFO 128 byte на RX, 256 на TX, но утилита должна пахать и на cp2102 и на pl2303, ибо кому тогда оно надо. С ожиданием все работает, но вот только решение кажется весьма странным. Неужели нет штатного механизма дождаться когда хардварное фифо опустеет.

AiFiLTr0 ★★★★★ ()
Последнее исправление: AiFiLTr0 (всего исправлений: 1)
Ответ на: комментарий от arsi

Блин... точно, у меня

tcsetattr(us->fd,TCSANOW,&newtio);

Но перед этим стоит tcdrain, если повторно вызывается. Спасибо, как в пнд приеду домой, проверю.

AiFiLTr0 ★★★★★ ()
Последнее исправление: AiFiLTr0 (всего исправлений: 1)
Ответ на: комментарий от AiFiLTr0

Не знаю, сам не использовал. Просто звёзды так совпали, что я читал в этот день «Linux. Системное программирование» Роберта Лава как раз про тот флаг. Да и man 2 open как бы намекает...

greek_31 ★★ ()
Ответ на: комментарий от AiFiLTr0

С O_DIRECT оно вообще не открывает порт, с руганью на Bad file descriptor. По ходу O_DIRECT не поддерживается для tty девайсов.

AiFiLTr0 ★★★★★ ()
Ответ на: комментарий от AiFiLTr0

Если ещё актуально, то вот мой совет: не изобретай велосипед, а делай как производители модемов. Это самое AT+IPR=0 всего навсего означает, что они тупо ищут "[Aa][Tt]" на разных скоростях.

vahtu ()
Ответ на: комментарий от AiFiLTr0

> Нет, TCSADRAIN не помогает.

хм… действительно, работает через раз. но это я на мохе проверил, сейчас поищу девайс на арме, там вроде нормально работало. может, потому что там 200МГц проц и успевало выдать :) но в любом случае, задержки придётся ставить :(

arsi ★★★★★ ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.