Pull to refresh

Comments 57

Очень подробный и ценный обзор, снимаю шляпу.


Мне не хватило в этой статье ключевых характеристик микросхем: как они относятся к дребезгу земли. Многие дешёвые микросхемы зависают, если идут помехи по земле, в силу плохих контактов. Именно поэтому я больше всего люблю FT232RL, не смотря на её цену, что она стабильно работает даже при самых плохих контактах.

Если расскажете про то, как можно было бы максимально корректно оттестировать этот аспект, то может быть (когда-нибудь) я дополню данную статью и таким исследованием. Платы у меня есть, микросхемы есть, почему бы и не? :)

Как вариант - протестировать на устойчивость к внешнему воздействию (наводки от трансформаторов и других высоковольтных или высокочастотных элементов устройства).
Просаживание напряжения сигнала
Добавление шума в сам сигнал (имитация плохого контакта и, опятьже, наводок)
Тест на заявленную термоустойчивость...

В общем - тесты на работу в экстремальных и не очень стандартных условиях.

Это тянет на хорошую научную работу, даже сложнее чем просто статья на хабр.

Я не могу придумать как качественно протестировать, разве что вручную отключать-подключать землю и так чтобы оба прибора питались от отдельных блоков питания и не имели общей земли (опасный эксперимент, на самом деле). Но прям конкретных советов не дам.


Я сталкивался с тем, что всякие PL2303 легко зависают из-за дребезга, и приходится перезагружать физическим отключением. Даже китайские FT232RL справляются с этим.

Многие дешёвые микросхемы зависают, если идут помехи по земле

Тут надо ещё отделить ситуацию "завис хост", которая имеет отличную от нуля вероятность.

Имеет, но чаще глючат микрухи. Это проверяется отсоединением от хоста и перемыканием RX-TX, проверку на эхо. Эха нет.

Хочу отметить, что когда я начинал писать данную статью, FT232RL числился в базе Маузера, хоть и с пометкой "нет в наличие". А сейчас его даже в базе нет. Похоже, NRND - не фигура речи и FTDI взяли решительный курс на сворачивание производства чипа-легенды.

Печально, печально. Слишком много подделок, видимо.


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

Он не только подорвал, но и еще ничему не научил - FTDI изобретателтно и задорно повторили :)

В разделе про драйверы я упомянул данную череду скандалов :)

Спойлеры обычно не читаются, пропустил.


Хотя подобное действие имело обратимый характер (в сети в скором времени появились инструкции по «раскирпичиванию» мостов FTDI), оно было воспринято сообществом крайне негативно. По некоторым сообщениям, «вишенкой на торте» была попытка протолкнуть данный драйвер в ядро Linux.

Иронично, что "окирпиченные" ftdi сейчас в новых ядрах корректно распознаются и работают.

на одном и том же компе (win10) в некоторых случаях работает, в некоторых выдает ругательство как на подделку. Чип, конечно же, поддельный )

Поэтому при выборе шнурков я отдаю предпочтение чисто китайскому CH340, он везде без проблем работает

Спойлеры обычно не читаются, пропустил.

В своих статьях я под спойлеры обычно убираю самое интересное :)

Напрасно, практика показывает что спойлеры читают не более пары процентов людей.

Ну хоть в чем-то я не как [почти] все. :)

Обеими руками за FT232! Её снимают с производства сейчас, думаю на что менять. Думать сложно так как надо тестировать месяцами чтобы понять надёжность, а это не всегда удобно.

Поддерживает один либо два стоп‑бита

Зачем два стоп-бита UART, если с одним стоп битом больше плотность данных?

Дать время успокоиться каналу между пакетами, например для длинных линий.

Кстати о птичках. Насколько я помню, второй стопбит обычно воспринимается исключительно как пауза для передатчика, зачастую приёмник 8N1 от 8N2 не отличает.

Если очень хочется контролировать, то можно использовать 8M1 (когда бит четности ставится в 1цу) (если UART поддерживает, конечно же)

Предположим, имеется классическая ATmega328P и требуется выжать из неё максимальную пропускную способность. Напрашивающимся решением является повысить битрейт на столько, на сколько это возможно. Битрейт в данных МК определяется делителем UBRR. Чтобы выжать из ATmega328P максимальный битрейт необходимо понизить делитель частоты UBRR как можно ниже. Но. При низких значениях UBRR его изменение будет весьма резко изменять битрейт.
При UBRR равном двум, битрейт будет равен f/16.
При UBRR равном трём, битрейт будет равен f/32.
При UBRR равном четырём, битрейт будет равен f/48.
Теперь представим, что символы приходят непрерывным потоком. При максимальном битрейте и символе 8N1 у ATmega328P будет 16 тактов между символами, чтобы обработать очередной символ. Если на обработку требуется, скажем, 20 тактов, то понижение битрейта понизит пропускную способность на 50%. А добавление ещё одного стоп-бита понизит её всего на 11%

Справедливым является вопрос: так ли уж надо обрабатывать очередной символ сразу же после его прихода? Не проще ли его скопировать в память, 16 тактов на это должно хватить, а затем обрабатывать столько, сколько идёт следующий символ? Да, проще - если данные между устройствами передаются длинными пакетами. Но если имеется подобие адресации (одно устройство передало один символ с адресом некоего регистра, второе - передаёт/возвращает данные из этого регистра) то в предельном случае такая конфигурация "отъедает" 33% пропускной способности (один символ - туда, один символ - ожидание/обработка, один символ - обратно). И тогда потеря 11% будет более предпочтительна.

На мой взгляд, субъективный и претенциозный, двойной стоп-бит - это архаика и экономия на спичках в ущерб единообразию.

Но я с интересом прочитаю любое другое объяснение применимости двойного стоп-бита, если оно будет обосновано весомыми аргументами.

Не обязательна даже адресация, если что-то на лету считается например (та же CRC) то уже могут быть проблем. Плюс 16 тактов объективно мало - не все команды все же за такт работают. Плюс что там компилятор сделает не известно.

Всё, что приходит по Rx, теоретически, можно буферизировать и ковыряться с ним весь следующий символ. Какая разница, выявит CRC сбой за паузу между символами или выявит в течение следующего символа? Всё равно - перепосылать.

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

Можно что угодно делать, но 16 тактов мало, а буферизация не всегда возможна - у мег, 1 КБ памяти, много туда набуферизируешь если МК не только с UART работает?

Забуферизировать надо только один символ.

Так UART сам буферизирует 1 символ, даже на 8051, разве нет?

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

Либо я не понимаю о чем идет речь :)

Я в 8051 порой вынужден был потратить 256 байт кода под табличку для упаковки обработки принятого символа чтобы hex2bin и bin2hex делать со всеми проверками максимально дёшево по тактам и ОЗУ -- и использовать буфер половинного объёма, основной поток мог обрабатывать медленно не задерживая коммуникацию в кольце вообще

По завершению приёма символа копируете за 16 тактов данные из регистра данных USART в однобайтовый буфер ОЗУ. И дальше работаете с символом в однобайтном буфере ОЗУ 16х8 (для 8N1) тактов. Тем временем следующий символ считывается в регистр данных USART.

Стоп. Мы говорим о 16 тактов на БИТ а не 16 тактов на БАЙТ?

О 16 тактах на бит. При 16 тактах на байт добавление/убавление второго стоп-бита погоды не сделает ни в каком случае.

ATmega328P будет 16 тактов между символами

Тогда вообще не складывается. У меги 1 буфер байт + байт который собирается (или это просто 2 байта буфер? давно трогал её). То есть у нас всегда есть время в полный байт на то чтобы забрать байт из входного регистра и свободить его для следующего.

В какой ситуации берётся требование что-то сделать строго за стоп-бит?

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

К слову, не совсем понял ваш пост про

Дать время успокоиться каналу между пакетами, например для длинных линий.

Если линия согласована, то нечему в ней успокаиваться.

Если линия не согласована, да так, что это мешает передаче, то по какой причине её не согласовали?

В любом случае, двойной стоп-бит от этого точно не поможет.

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

Логично, но тогда непонятно чем второй стопбит изменит ситуацию -- мы просто меняем шило (разрешение в N бит паузы перед ответом) на мыло (1 бит к каждому входному байту всегда). Но теперь я идею понял :)

Если линия не согласована, да так, что это мешает передаче, то по какой причине её не согласовали?

Да, терминатор на конце линии помогает лучше всего для гарантии. Второй стопбит, который почти все приёмники игнорируют, даёт время избавиться от "звона" от передачи. Для передачи с большим количеством пауз (длинных последовательностей единиц) вообще это никак не помогает, а эксперименты которые мы проводили показывали что 8n2 эффективно подавляет "левый" приём на стороне компа при использовании телефонного кабеля и COM<=>(токовая петля) конвертера. (по осцилографу там всплески где-то в 5% амплитуды были, который MAX радостно конвертировал в нечто более высокое, которое комп распознавал за старт)

При переходе на USB адаптеры лет 10 назад оно осталось уже в форме legacy. Наверное, интересно было бы перепроверить -- есть ли еще польза какая от второго стопа или нет :) Но у меня нет сейчас лабы под руками.

Я просто понять не могу, допустим есть некое отражение, которое за один стоп-бит не успокаивается, а за два стоп-бита успокаивается. Ну ок. Стоп-биты теперь распознаются. Но в "теле" символа будет белиберда как ни крути. Если мы передаём символ 00010000, то мы точно так же получим на принимающей стороне 00011000 или 00010100 из за отражений.

Во время передачи, передатчик довольно эффективно давит отражения, успешно как подтягивая вверх так и утаскивая вниз. После передачи он отцепляется от линии возваращя туда приёмник, в итоге на линии становятся все приёмники, то есть никто линию никуда тянет -- и шум начинает влиять. И да, я не думаю, что проблема проявляется на связи точка-точка.

mea culpa, условия в которых проблема встречается, следовало сразу определить...

Мне кажется, где-то в коде закралась ошибка произошло неявное преобразование типа тактов. От тактов основного генератора (которые для AVR и лучших представителей MCS-51 равны времени выполнения команд) к тактам блока USART (которые, в общем случае, в N=2<sup>M</sup> раз длиннее).

Ну, например, Modbus использует 11 бит:

1старт + 8бит_данных + 1четность + 1стоп (8E1, как обязывает стандарт поддерживать по умолчанию)

либо

1старт + 8бит_данных + 2стоп (8N2, как дополнительная возможность).

А вообще, скорее всего, чтобы не копить ошибку, связанную с неточностью битрейта. У приемников многих микросхем нет настроек на 2 стоп-бита, а только на один. Стало быть, второй стоп-бит - как пауза в посылках. И каждая новая посылка начинает тактироваться "с чистого листа".

Ошибка эффективно обнуляется и после одного стоп-бита.

Зависит от приемника. Если приемник переходит в ожидание готовности старта после половины стопа -- да, обнуляется. Если приемник ждет полного стоп бита, то расхождения частот в 5% достаточно для стабильной потери связи.

5% на бит? Типа, чтобы на 10 битах получить 50% ? Ммм. На каком оборудовании вы получали такое расхождение длительности бита? Просто даже если взять, скажем MCP2221 и врубить ему нетипичный именно для него битрейт 128000 бит/с, то там расхождение от ошибки деления частоты будет 7,3%. На весь символ. Не на бит. У всех остальных мостов ошибка от деления частоты на весь символ набегает, ну, процента 1,5%. А то и меньше.

Не, если эта ATmega328P, используемая в расширенном температурном диапазоне и затактированная от внутреннего генератор, который будет гулять на предельных температурах на 14%, то да. Но там и двойной стоп-бит не поможет )))) Там, думаю, нужно будет как раз 5-битными символами общаться, чтобы погрешность не набегала )))

Да, речь именно про запитку от внутренних генераторов когда они стоят в разных концах комнаты с градиентом в 20 с лишним градусов (а то и выше).

причем да -- для случая когда стоп ловится в середине это не проблема (набежать должно больше 50%), а вот когда стоп ловится ближе к концу бита в принципе -- рассинхрон встречался достаточно часто, чтоб на 2 стопа переключиться.

Если разность температур постоянна и на одном из концов FT232RL, то при битрейте 9600 бит/с делитель позволяет подкручивать битрейт с шагом приблизительно в 0,1%. Имело бы смысл тогда подстроиться под приёмник.

Но. Если...

  • Градиент "20 с лишним градусов" и при этом он не фиксирован - постоянно меняется

  • Скорость хочется сделать в районе мегабитов в секунду, следовательно делителем особо точно битрейт уже не понастраиваешь. Либо он в принципе не настраиваем.

  • Обе стороны затактированы от внутренних RC и подсунуть кварцы нет никакой возможности

...то да, дело - дрянь ))))

Представляется, что применение в таком случае двойного стоп-бита (который - раз! и поможет) - это заплатка. Это не то что, двойной стоп-бит обладает какими-то супер-ценными фишками. Градиент станет чуть побольше - и эта заплатка также порвётся. Придётся урезать уже количество бит в символе )))

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

RTS/CTS и DTR/DSR

В моей любительской практике наличие процитированного довольно критично, потому что используется в качестве GPIO для управления внешними устройствами. Конкретный пример: любительская радиостанция, которая по UART получает/отдает основные данные для управления собой и отчета о состоянии, вроде установки частоты и режима работы, независимо использует линии RTS и DTR для переключения прием/передача и FSK (радиотелетайп) манипуляции. Соответственно, поддержка этих линий отладочными платами более чем интересна, хоть и немного выходит за рамки голого UART, вторгаясь уже в RS-232.

Хотел бы отметить. Среди рассматриваемых мостов:

  • у CH340N в корпусе SOP-8 есть только RTS (очевидно в SOIC-8/SOP-8 физически не засунуть сразу все RTS/CTS/DTR/DSR)

  • у PL2303GL в корпусе SOP-8 после раскидывания шести обязательных выводов D+/D-/Tx/Rx/Vin/GND на оставшиеся два свободных инженеры повесили выход LDO и Vddio

  • у MCP2221A несмотря на то, что выводов хватает, нет ни одного вывода из RTS/CTS/DTR/DSR

  • у CP2102N-A02-GQFN20 есть RTS/CTS, но нет DTR/DSR

И мне любопытно, в тех любительских радиостанциях, о которых вы говорите, наличие у моста выводов RTS/CTS/DTR/DSR является обязательным или опциональным? То есть возможно ли управлять данными радиостанциями при помощи исключительно команд, передающихся через Tx?

В любом случае, я осознаю, что в индустрии имеется оборудование, которое в силу исторических причин требует наличия данных выводов. Однако, по моему субъективному и претенциозному мнению, в новом, проектируемом оборудовании от использования данных линий стоит отказываться.

Соответственно, поддержка этих линий отладочными платами более чем интересна, хоть и немного выходит за рамки голого UART, вторгаясь уже в RS-232.

Тут ещё как знать, кто более голый: UART, у которого отсутствует формализованный стандарт (UART - это просто набор традиций) или RS-232, который содержит электрические параметры, размеры разъёмов и наименование выводов, но не содержит ни правил передачи, ни стандартных битрейтов, ни стандартных длин символов :)

Возможность минимального квитирования (RTS/CTS) считаю весьма полезной.

Если говорить о передаче данных в узком смысле, то современный UART в большей мере является протоколом передачи команд и в меньшей - протоколом передачи данных (в смысле, большого объёма однородных данных - видеопотока, скажем).

Да, есть ситуации, когда определённые команды временно не возможны к исполнению устройством. Воображаемый пример: нельзя выполнять команду раскручивания аэростатического подшипника, если в него не подано достаточное давление. Если мы по Tx подаём подряд команды "подать давление в пневматику" и "раскрутить подшипник", то было бы разумным получить по Rx в ответ на вторую команду код ошибки - почему команда "раскрутить подшипник" не может быть сейчас выполнена. Объявление неготовности устройства через CTS здесь кажется более чем неуместным.

Если мы говорим о передаче потока данных, то, положа руку на сердце, можете ли вы сказать, что сейчас есть устройства, которые могут не успеть как-то там переварить данные от потока 9600 бит/с так, что придётся его временно останавливать? Да и даже 12 Мбит/с. Я пытаюсь, но не могу придумать ни класс таких устройств, ни хотя бы какое-то уникальное устройство. Если вы назовёте пример, пусть даже и умозрительный, мне будет весьма любопытно его прочитать.

При этом исторически, назначение подобных выводов более чем понятно. Когда нужно было переливать, скажем, 115200 бит/с в 9600 бит/с и наоборот, тут без квитирования никак. Да, UART вырос из модемов. А для модемов подобный функционал - RTS/CTS - более чем полезен. Но это всё в прошлом.

Но это всё в прошлом.

Пример из личного опыта годовой давности: сливал через USB-UART адаптер на скорости 115200 дамп прошивки с Xiaomi-вской рации на комп, командами встроенного в прошивку рации терминала. Так вот, совершенно для меня неожиданно, оказалось, что при передаче блоков более определённой длины, данные портятся со 100% вероятностью, причём длина эта для разных USB-UART отличается: для адаптеров на "китайцах" ch340, pl2303 ошибки возникали, когда длина блока превышала ~40 байт, для ft232rl - ~1К байт; полное впечатление, что при заполнении внутреннего буфера адаптер какое-то время тормозит, а передатчик продолжает отсылать данные - и часть этих данных благополучно теряется. Была бы возможность у приёмника на время раздумий снять CTS - не было бы никаких проблем, да только вот у рации TXD/RXD есть а CTS/RTS нетути... пришлось написать скрипт который дамп кусочками по 16 байт снимает.

И у FTDI и у CP были флаги в реестре которые позволяли поднять частоту поллинга. Если моя память не подтекает, то у FTDI дефолт около 15мс. Я снижал до 3-5мс чтоб получить стабильную связь на больших скоростях с минимальными задержками.

https://www.ftdichip.com/Support/Knowledgebase/index.html?settingacustomdefaultlaten.htm

16ms дефолт. На 1-2 становилось хуже, а на 3-5 сильно лучше при обмене

Флаги в реестре полезны там где есть реестр :)

Но вообще спасибо, не знал. Пригодится!

На линуксе тоже: https://granitedevices.com/wiki/FTDI_Linux_USB_latency

А, там еще крутилка размера USB буфера, которая может потребоваться для получения стабильных бОльших скоростей. Я редко выше 57600 использовал, поэтому размер буфера не крутил

У платок на esp DTR/RTS это практически стандарт для сброса и включения режима программирования.

За статью спасибо, монументально.

Вот за это я и не очень люблю все эти дополнительные линии как в статьях, так и в практике:

  1. Сначала долго разбираемся в их штатном функционале.

  2. Затем внезапно понимаем, что штатный функционал глубоко историчен.

  3. Начинаем использовать их как GPIO0 и GPIO1 для абсолютно произвольных назначений. Но только без IO - либо "I", либо "O".

  4. А когда нам требуется GPIO2, понимаем, что GPIO2 взять неоткуда и этот функционал всё равно нужно реализовывать поверх символов UART-а.

Я осознаю, что желание стройности, унификации и единообразия - это определённый снобизм и что почти все стандарты изрезаны временем, временными наколеночными решениями, которые стали чем-то на редкость постоянным. Но. Веет от этих дополнительных линий RTS/CTS/DTR/DSR брючным ремнём, накинутым на валы взамен лопнувшей штатной ременной передачи :)

За статью спасибо, монументально.

Приятно слышать!

Мне тоже не нравится, особенно это логическая конструкция на транизсторах, сделанная для обхода обычного поведения DTR/RTS, как я понимаю.

Мы у себя просто взяли IO-линии на FT-что-то-там, где два порта, и второй порт сконфигурировали как GPIO, им и рулим.

И мне любопытно, в тех любительских радиостанциях, о которых вы говорите, наличие у моста выводов RTS/CTS/DTR/DSR является обязательным или опциональным?

Обмен данными, неважно - аппаратно это уровни TTL или RS-232, использует, где я знаю, только RXD, TXD и GND. Дополнительные линии используются для манипуляции логическими уровнями вне. Однако, физически, они предполагаемая часть полноценного коммуникационного порта и софт, управляющий радиостанций, пишет или читает уровни дополнительных линий в дополнение. Мосты же часто оказываются неполноценными в части поддержки хотя бы нескольких линий сверх RXD, TXD и GND.

То есть возможно ли управлять данными радиостанциями при помощи исключительно команд, передающихся через Tx?

В некоторых невозможно, в смысле не поддерживается такая команда в принципе, и во всех нежелательно из-за задержек. Манипуляция логическим уровнем работает быстрее и надежнее, поскольку не тратит время на формирование команды, ее отправку, обработку получателем, ну и значительно меньше подвержена сбоям. Все-таки радиостанция - это источник RFI, а значит риски помех самой себе у нее выше среднего. С дискретным логическим уровнем все сильно проще.

В любом случае, я осознаю, что в индустрии имеется оборудование, которое в силу исторических причин требует наличия данных выводов. Однако, по моему субъективному и претенциозному мнению, в новом, проектируемом оборудовании от использования данных линий стоит отказываться.

В моем примере - едва ли отказ от этих линий оправдан и произойдет кого-то в ближайшем будущем. Пока я вижу тенденцю переносить мост внутрь радиостанции, которая теперь подключается бытовым USB кабелем, но сохраняет и выведенный наружу RS-232 или TTL для совместимости с более старым внешним оборудованием. Естественно, нужно рассматривать конкретные модели, но в среднем где-то так.

Тут ещё как знать, кто более голый: UART, у которого отсутствует формализованный стандарт (UART - это просто набор традиций) или RS-232, который содержит электрические параметры, размеры разъёмов и наименование выводов, но не содержит ни правил передачи, ни стандартных битрейтов, ни стандартных длин символов :)

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

nRST. Позволяет устройству отключить мост при необходимости.

КМК - надо поправить формулировку. "Отключить" - можно понять как "Понизить энергопотребление до мыслимого минимума". А сброс - совсем не про это.

Вообще - шикарно! Спасибо! Виртуальный второй плюс в карму.

Sign up to leave a comment.

Articles