I've just tried following
the kernel docs for RS485 with a logic analyser connected to TXD and RTS. I was using UART3 on a Pi4, so GPIO 4 for TXD, and GPIO 7 for RTS using "dtoverlay=uart3,ctsrts" in /boot/config.txt.
Code: Select all
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <linux/serial.h>
/* Include definition for RS485 ioctls: TIOCGRS485 and TIOCSRS485 */
#include <sys/ioctl.h>
int main(void)
{
int ret;
/* Open your specific device (e.g., /dev/mydevice): */
int fd = open ("/dev/ttyAMA1", O_RDWR);
if (fd < 0) {
/* Error handling. See errno. */
}
struct serial_rs485 rs485conf = {0};
/* Enable RS485 mode: */
rs485conf.flags |= SER_RS485_ENABLED;
/* Set logical level for RTS pin equal to 1 when sending: */
rs485conf.flags |= SER_RS485_RTS_ON_SEND;
/* or, set logical level for RTS pin equal to 0 when sending: */
//rs485conf.flags &= ~(SER_RS485_RTS_ON_SEND);
/* Set logical level for RTS pin equal to 1 after sending: */
//rs485conf.flags |= SER_RS485_RTS_AFTER_SEND;
/* or, set logical level for RTS pin equal to 0 after sending: */
rs485conf.flags &= ~(SER_RS485_RTS_AFTER_SEND);
/* Set rts delay before send, if needed: */
//rs485conf.delay_rts_before_send = ...;
ret = ioctl (fd, TIOCSRS485, &rs485conf);
if (ret < 0) {
/* Error handling. See errno. */
printf("ioctl failed %d, errno %d\n", ret, errno);
}
/* Use read() and write() syscalls here... */
write(fd, "FOO BAR", 7);
/* Close the device when finished: */
if (close (fd) < 0) {
/* Error handling. See errno. */
}
return 0;
}
Makefile
Code: Select all
CROSS_COMPILE ?=
CC := $(CROSS_COMPILE)gcc
CFLAGS ?= -O2 -W -Wall -std=gnu99
LDFLAGS ?=
LIBS := -lrt
%.o : %.c
$(CC) $(CFLAGS) -g -c -o $@ $<
all: rs485
rs485: rs485.o
$(CC) $(LDFLAGS) -o $@ $^ $(LIBS)
clean:
-rm -f *.o
-rm -f rs485
Run that and I get the following trace

- RS485.png (176.48 KiB) Viewed 2060 times
With the exception of the 0.5us blip after the message, that is exactly what I'd expect. If RTS is connected to DE and nRE on a MAX3485 or similar, the transmitter will be enabled whilst there is data to send, and then drops back to receive mode.
The RS485 setting appears to be retained after the device is closed, so running "cat /boot/config.txt > /dev/ttyAMA1" afterwards also sends the data in exactly the way I'd expect (RTS taken high whilst there is data being actively sent).
The blip looks odd, but would need a fair amount of studying the driver to work out what is going on.
If I "cat Makefile" to ttyAMA1 then I get a couple of blips during the message, but they are always at byte boundaries. RS485 should have bias resistors on the line, so all drivers being disabled should result in a defined state that is the same as the stop state. It should therefore be harmless. At a guess the "cat" is being slow at refilling the FIFO, so the driver sees nothing more to send and drops RTS.
Software Engineer at Raspberry Pi Ltd. Views expressed are still personal views.
I'm not interested in doing contracts for bespoke functionality - please don't ask.