Pull to refresh

Comments 24

Возможно, вместо FNDELAY корректнее использовать O_NONBLOCK.

Хороший вопрос, и в комментариях к статье на изиэлектроникс было обсуждение. Фишка в том, что это одно и то же.
man fcntl
F_SETFL (int)
Set the file status flags to the value specified by arg. File access mode (O_RDONLY, O_WRONLY,
O_RDWR) and file creation flags (i.e., O_CREAT, O_EXCL, O_NOCTTY, O_TRUNC) in arg are ignored.
On Linux, this command can change only the O_APPEND, O_ASYNC, O_DIRECT, O_NOATIME, and O_NONBLOCK
flags. It is not possible to change the O_DSYNC and O_SYNC flags; see BUGS, below.


Если посмотреть файл /usr/include/x86_64-linux-gnu/bits/fcntl-linux.h, то увидим там такое:

# define FNONBLOCK O_NONBLOCK
# define FNDELAY O_NDELAY
Одно и то же, но FNDELAY устарел и был непереносим, POSIX рекомендует O_NONBLOCK (а внутри конечно оно может и одно и тоже почти везде).
Спасибо за дополнение.
Далеко за примером ходить не надо, внутри смартфона, лежащего у вас в кармане, будет с десяток UART интерфейсов, самый известный из которых — это подключение SIM-карты.
Пример с SIM-картой как раз неудачный — там используется синхронный интерфейс передачи данных, который больше похож не на UART, а на I2C: есть двунаправленная линия передачи данных и отдельный сигнал тактирования.

Подозреваю там USART, который тогда уж больше похож на SPI.

Не совсем так, clock там тактирует карту, а не является стробом для передаваемых битов.
Хм, спаиваем вместе rx и tx, и тактируем их :). На самом деле, я не придумываю ничего, так как SIM-карты читал с помощью UART-переходника, и они попадают в стандарт. Подробнее вот в этой статье. Цитата от туда:

Сразу скажу, что T0 как две капли воды похож на UART (он используется в передаче по COM-порту). Но с небольшими оговорками. Начнем с самого начала.
Там ближе к USART всё дело, к примеру ISO7816 на микроконтроллерах AT32 вообще через UART контроллер аппаратно сделано (отдельный режим работы, который покрывает базу 7816-3).

В каком месте I2C синхронный?

Сорьки, виноват! Всегда думал, что под синхронностью понимается способность одновременно как выставлять, так и принимать данные.

В наличии тактового сигнала, которого нет в UART.

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

open(2) — Linux manual page

The return value of open() is a file descriptor, a small, nonnegative integer that is an index to an entry in the process's table of open file descriptors.

Если количество count равно нулю, то read() возвращает это нулевое значение и завершает свою работу. 

Не так безобидно, см.

read(2) — Linux manual page

If count is zero, read() may detect the errors described below. In the absence of any errors, or if read() does not check for errors, a read() with a count of 0 returns zero and has no other effects.

например

EFAULT buf is outside your accessible address space.

On error, -1 is returned, and errno is set to indicate the error. In this case, it is left unspecified whether the file position (if any) changes.

По поводу фотографии в начале поста . Работал на таком в молодости. Но мне больше нравился такой как на фотографии ниже (справа). На него можно было пиво поставить.

Вы осознаёте теперь всю сложность работы с COM-портом? При этом мы не разобрали даже половины его возможностей, а уже это оказывается дико сложным. 

Теперь осознал. Буду требовать повышения зарплаты.

Да очень просто, если у вас режим передачи RS-485 управляется линией DTR/RTS, либо GPIO, то вы должны точно знать, когда данные были отправлены, чтобы правильно выставить эти пины, меняя режим передачи на приём.

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

По моему скромному мнению управлять направлением RS485 линией DTR/RTS - не слишком хорошее решение, а для линукса, даже на уровне драйвера ядра (если в контроллере нет аппаратной поддержки), практически невозможное. Поскольку линукс не система реального времени, а живёт как подобного рода системы богатой внутренней жизнью, то гарантировать заданное время переключения невозможно и в этом случае работают только внешние аппаратные решения.

По моему скромному мнению управлять направлением RS485 линией DTR/RTS — не слишком хорошее решение, а для линукса, даже на уровне драйвера ядра (если в контроллере нет аппаратной поддержки), практически невозможное. Поскольку линукс не система реального времени, а живёт как подобного рода системы богатой внутренней жизнью, то гарантировать заданное время переключения невозможно и в этом случае работают только внешние аппаратные решения.

В современных реалиях это будет достаточно быстро. Хотя, без сомнения решение кривое. Проблема в том, что оно часто встречается в аппаратной реализации.

Согласен. Похоже, что это нужно на уровне драйвера решать - отлавливать прерывание о том, что TX-FIFO пуста (если она есть) и регистр данных тоже пуст и тогда уже переключать направление. Правда не уверен, что такое возможно на ПК, т.к. с ними ни разу не работал с UART'ами - только arm cortex-m[0,3,4]

Правда не уверен, что такое возможно на ПК, т.к. с ними ни разу не работал с UART'ами — только arm cortex-m[0,3,4]

Всё зависит от аппаратной реализации. Сейчас чаще шнурки на USB на базе FTDI

Для cp210x в документации (AN571.pdf) указано, что можно включить событие "bit 10: The transmit queue is empty" и по нему уже направление RS-485 переключать. Про FTDI, Prolific и CH341A нужно читать - с ними не работал на низком уровне.

Sign up to leave a comment.