Hi,
I'm trying to get RS485 running on our custom i.MX7D based board.
I can write some data to RS485 correctly, but when any data is received, there are some random data automatically generated to the line probably by imx.c driver. I have tried to interconnect 2 RS485 lines, open them from C++ code and just write few bytes to one of them and it results in endless pinging of random data on the line.
Both RS485 are working in half-duplex mode with SN65HVD1780 chip, direction control using RTS as GPIO.
Devicetree (UARTS are aliased to ports 2,3):
&uart4 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_uart4>;
assigned-clocks = <&clks IMX7D_UART4_ROOT_SRC>;
assigned-clock-parents = <&clks IMX7D_OSC_24M_CLK>;
rts-gpios = <&gpio3 21 GPIO_ACTIVE_HIGH>; //DIR control
linux,rs485-enabled-at-boot-time;
rs485-rts-delay = <1 1>; // in milliseconds
status = "okay";
};
&uart6 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_uart6>;
assigned-clocks = <&clks IMX7D_UART6_ROOT_SRC>;
assigned-clock-parents = <&clks IMX7D_OSC_24M_CLK>;
rts-gpios = <&gpio3 22 GPIO_ACTIVE_HIGH>; //DIR control
linux,rs485-enabled-at-boot-time;
rs485-rts-delay = <0 1>; // in milliseconds
status = "okay";
};
Part of testing code:
bool InitRS485(int fd)
{
struct serial_rs485 rs485conf;
rs485conf.flags |= SER_RS485_ENABLED; //Enable RS485 mode
rs485conf.flags |= SER_RS485_RTS_ON_SEND; //Set logical level for RTS pin equal to 1 when sending
rs485conf.flags &= ~(SER_RS485_RTS_AFTER_SEND); //Set logical level for RTS pin equal to 0 after sending
rs485conf.delay_rts_before_send = 1; //Set rts delay before send
rs485conf.delay_rts_after_send = 1; //Set rts delay after send
if(ioctl(fd, TIOCSRS485, (void*)&rs485conf) == 0)
{
struct termios tty; //Get current settings
if(tcgetattr(fd, &tty) == 0)
{
tty.c_cflag &= ~PARENB; //No Parity
tty.c_cflag &= ~CSTOPB; //1 Stop Bit
tty.c_cflag &= ~CSIZE;
tty.c_cflag |= CS8; //8 Bits
cfsetspeed(&tty, 19200); //Set baudrate
if(tcsetattr(fd, TCSANOW, &tty) == 0) //Set settings to port
{
return true;
}
}
}
return false;
}
void rs485TaskTest1()
{
int fd = open("/dev/ttymxc2", O_RDWR);
if (InitRS485(fd))
{
const uint8_t data[] = { 0x11, 0x01, 0x02, 0x32, 0x00};
write(fd, data, sizeof(data));
}
close(fd);
}
void rs485TaskTest2()
{
int fd = open("/dev/ttymxc3", O_RDWR);
if (InitRS485(fd))
{
while (1)
{
std::this_thread::sleep_for(100ms);
}
}
close(fd);
}
As you can see, I'm writing on first RS485 and just opening port on second with sleeping.
Result caught on analyzer (1 - DIR, 2 - RX, 3 -TX):
As you can see, there is also problem, that on first transition with normal data, RTS delay before send (delay_rts_before_send) is not applied. On randomly generated transitions it is applied correctly.
Any ideas, what am I doing wrong, or I have hit some kind of bug?
I'm running kernel version 5.15.52. I have tried to backport changes in imx.c from 6.x kernel, but with same results.
Thanks in advance,
Michal Špánik
Solved! Go to Solution.
Hello,
Have you tried usin latest kernel instead of backporting?
Also, you may try using test code we have available under unit_test:
https://github.com/nxp-imx/imx-test/blob/lf-6.6.3_1.0.0/test/mxc_mcc_tty_test/mxc_mcc_tty_test.c
https://github.com/nxp-imx/imx-test/blob/lf-6.6.3_1.0.0/test/mxc_uart_test/mxc_uart_test.c
Best regards/Saludos,
Aldo.
To simplify the usecase, this happens, when I
echo "12345" > /dev/ttymxc3
with interconnected port 2 and 3 (port 2 is with connected analyzer)
It seems OK. But when I run
cat /dev/ttymxc2
and
echo "12345" > /dev/ttymxc3
which opens the receiving port (but does not process data in any way), it looks like this:
It seems, that data is automatically echoed back to transmit after receive (even with correct RTS).
If I disable DMA, First byte is echoed immediately and rest of data is cut (because of direction change).
Hello,
Have you tried usin latest kernel instead of backporting?
Also, you may try using test code we have available under unit_test:
https://github.com/nxp-imx/imx-test/blob/lf-6.6.3_1.0.0/test/mxc_mcc_tty_test/mxc_mcc_tty_test.c
https://github.com/nxp-imx/imx-test/blob/lf-6.6.3_1.0.0/test/mxc_uart_test/mxc_uart_test.c
Best regards/Saludos,
Aldo.
Hi,
I found call to
cfmakeraw()
in second test code, which seems to solve the issue. It was caused by ISIG flag, which is set by default and probably triggers on transferred data in our protocol/my test scenario.
Thank you very much for your support,
Michal Špánik