LINUX.ORG.RU

Можно узнать отправлены ли данны по UART?

 , ,


0

1

Использую BeagleBoard передаю данные по протоколу ModBusRTU через RS485. Для того чтобы отправлять данные и принимать данные RTS выставлюя его в 0 при приеме и 1 при передаче реализовал это с помощью временных задержек. Так как это не надежно нужно реализовать это без них. Теперь сам вопрос как можно узнать что данные ушли из одноплатника чтобы можно переключить RTS.

Осцилограф подключить не пробовал? Если задача просто узнать, что данные ушли — IMHO, замечательное решение

XMs ★★★★★
()

Кольцо. Tx на Rx.

Zubok ★★★★★
()

если другая сторона ответила

Harald ★★★★★
()

не используй rts, а только ответ принимающей стороны, что данные ею получены и контрольная сумма верна

x905 ★★★★★
()

Есть несколько сценариев, при больших скоростях и потоковой передаче используют ножки RTC/CTS, еще используют софтверный Xon/Xoff.

При более мягких требованиях работать в режиме посылка<->ответ с подтверждением.

Miha
()
Ответ на: комментарий от XMs

Мне нужно программно каждый раз узнавать что данные ушли а что можно было осуществлять переключение RTS а так то данные уходят мне нужно знать когда

vlad961996
() автор топика
Ответ на: комментарий от x905

Мне это нужно чтобы я правильное время мог переключить RTS иначе если я его не переключу то данные принять я просто не смогу

vlad961996
() автор топика
Ответ на: комментарий от vlad961996

кто заставляет тебя использовать ножки RTS ?
даже с ними тебе нужно быть уверенным в получении на том конце - а это только обратная квитанция
итого - rts ненужно

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

У меня есть промышленный интерфейс RS485 в котором нужно переключать pin иначе я могу данные только отправлять или только принимать. Вопрос я могу обойтись без переключения, если я просто не смогу принимать данные. Если знаете способ как обойтись без этого не меняя аппаратную часть, то объясните пожалуйста.

vlad961996
() автор топика
Ответ на: комментарий от vlad961996

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

Ты этот флаг анализируешь в цикле или разрешаешь прерывания при его появлении. Это классический uart. Возможно у тебя uart работает через DMA, там процессор в передаче не участвует, тут все специфично для конкретной железки какая инфа доступна в цикле передачи, но скорей всего тоже будет прерывание по окончанию передачи, только не одного байта а всего буфера.

Miha
()

смотри как оформлен буфер передаваемых данных в програмном драйвере.

условие при котором всЁ передалось окончание буфера и окончание работы конвейера передающего модуля.

обычно сделано так: аппаратный модуль уарт формирует прерывание по окончании передачи байта. на прерывание в драйвере уарт навешана функция, которая записывается следующий байт из буфера передачи и запускается аппаратный модуль на передачу байта. плюс идет работа с указателем буфера передачи.
измени функцию драйвера так что бы она обнуляла RTS при окончании буфера передачи и будет тебе счастие. так же можно можно дополнить функции начала передачи для включения RTS.

ну в общем смотри функции работы с уарт модулем в твоей ос.

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

Вот же ядрен батон! А кто тебе мешает вместо RTS дергать это любой свободной ногой GPIO? А еще, как советовали выше, сделать петлю на Rx.

Либо, раз ты такой умный, лезь в исходники модуля ядра своего UART'а и добавляй какой-нибудь сисвызов, чтобы удостовериться, что все ОК и данные из буфера ушли.

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

Я дрыгаю свободным gpio. по поводу петли объясните имеете виду замкнуть tx в rx то тогда не мой вариант

vlad961996
() автор топика

Использую BeagleBoard

какой у них драйвер уарта используется - разве там нет поддержки для переключения полудплексного трансивера rs485 ? мне кажется что вы изобретаете велосипед

https://elixir.bootlin.com/linux/latest/source/drivers/tty/serial/omap-serial...

https://elixir.bootlin.com/linux/latest/source/drivers/tty/serial/8250/8250_o...

anonymous
()
Ответ на: комментарий от vlad961996

tx_ready. Это может называться как угодно. Я бы взял исходники драйвера serial используемой версии линукс и посмотрел есть ли там поддержка 485 и как она сделана, скорей всего там будут какие-то специфичные ioctl.

Miha
()
Ответ на: комментарий от vlad961996

У меня есть промышленный интерфейс RS485 в котором нужно переключать pin

Если у тебя BeagleBoard с omap-serial драйвером,то там уже что-то есть для поддержки RS485:

https://elixir.bootlin.com/linux/latest/source/drivers/tty/serial/omap-serial...

/* Handle RS-485 */
if (port->rs485.flags & SER_RS485_ENABLED) {
  if (up->scr & OMAP_UART_SCR_TX_EMPTY) {
    /* THR interrupt is fired when both TX FIFO and TX
     * shift register are empty. This means there's nothing
     * left to transmit now, so make sure the THR interrupt
     * is fired when TX FIFO is below the trigger level,
     * disable THR interrupts and toggle the RS-485 GPIO
     * data direction pin if needed.
     */
    up->scr &= ~OMAP_UART_SCR_TX_EMPTY;
    serial_out(up, UART_OMAP_SCR, up->scr);
    res = (port->rs485.flags & SER_RS485_RTS_AFTER_SEND) ? 1 : 0;
    if (gpio_get_value(up->rts_gpio) != res) {
      if (port->rs485.delay_rts_after_send > 0)
        mdelay(port->rs485.delay_rts_after_send);
      gpio_set_value(up->rts_gpio, res);
    }
  }
}
alx777 ★★
()
Ответ на: комментарий от Miha

Примерно так:

#include <linux/serial.h>

	/* Driver-specific ioctls: */
	#define TIOCGRS485      0x542E
	#define TIOCSRS485      0x542F

	/* Open your specific device (e.g., /dev/mydevice): */
	int fd = open ("/dev/mydevice", O_RDWR);
	if (fd < 0) {
		/* Error handling. See errno. */
	}

	struct serial_rs485 rs485conf;

	/* Set RS485 mode: */
	rs485conf.flags |= SER_RS485_ENABLED;

	/* Set rts delay before send, if needed: */
	rs485conf.flags |= SER_RS485_RTS_BEFORE_SEND;
	rs485conf.delay_rts_before_send = ...;

	/* Set rts delay after send, if needed: */
	rs485conf.flags |= SER_RS485_RTS_AFTER_SEND;
	rs485conf.delay_rts_after_send = ...;

	if (ioctl (fd, TIOCSRS485, &rs485conf) < 0) {
		/* Error handling. See errno. */
	}

	/* Use read() and write() syscalls here... */

	/* Close the device when finished: */
	if (close (fd) < 0) {
		/* Error handling. See errno. */
	}

Miha
()
Ответ на: комментарий от vlad961996

Это все есть в документации ядра

https://elixir.bootlin.com/linux/latest/source/Documentation/serial/serial-rs...

еще там есть параметр в DTS

linux,rs485-enabled-at-boot-time: empty property telling to enable the rs485

https://elixir.bootlin.com/linux/latest/source/Documentation/devicetree/bindi...

и можно работать сразу как с обычным последовательным портом любыми консольными утилитами echo/cat .., только не забывать что он полудуплексный

anonymous
()

Зачем вообще заморачиваться с rts, если ты пишешь ModbusRTU, а не драйвер serial интерфейса?

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