Configuring RS485 for Verdin AM62 Ivy Board for Modbus RTU

Hello,
I am working on a Verdin AM62 connected to an Ivy Board. We are using Torizon OS and are configuring it with Torizon Core Builder. Recently our project has required that we add support for RS-485 devices, and we have had some trouble with it. The Ivy Board has support for RS-485 through the J6 Connector which we have wired in. We started by just working with our existing setup, simply connecting the wires and attempting to read Modbus RTU data using the mbpoll cli tool. We started with the port /dev/ttyS2, but also tried port /dev/verdin-uart2. Both of these gave back CRC errors or improper slave address errors for Modbus, which meant we were probably communicating but receiving the wrong packets back. Research led us to look into setting a device tree overlay, so we added this overlay to our Torizon Core Builder project:

/dts-v1/;
/plugin/;

/ {
    compatible = "toradex,verdin-am62", "ti,am625";
};

&main_uart2 {
    linux,rs485-enabled-at-boot-time;
    rs485-rts-active-high; 
    rs485-rts-delay = <1 1>;
    status = "okay";
};

We built that image and loaded it onto a board and the AUX1 light turned on which we have not seen before so we took that as a good sign. Trying mbpoll again both on ttyS2 and verdin-uart2 lead to getting a connection timed out error every time. Looking into this more we noticed that ttyS2 was being used by the console, so we added a kernel argument to have the console use tty1. It still gives the connection timed out error however so we are stuck.

Is there something we are missing to enable RS485? We are not familiar with device trees and haven’t required any changes to kernel args or anything like that for our project up to this point. Any help would be appreciated.

tdx-info summary:

Software summary
------------------------------------------------------------
Bootloader:               U-Boot
Kernel version:           6.1.119-6.8.2+git.92dbabd95f8f #1-TorizonCore SMP PREE                                      MPT Wed Feb  5 10:48:17 UTC 2025
Kernel command line:      root=LABEL=otaroot rootfstype=ext4 quiet logo.nologo v                                      t.global_cursor_default=0 plymouth.ignore-serial-consoles splash fbcon=map:3 ost                                      ree=/ostree/boot.1/torizon/6a80bb9e1a65ab32aaf04b640a8bea0562d8459fe1645bb6229b8                                      ae4768f8053/0 console=tty1
Distro name:              NAME="TorizonCore"
Distro version:           VERSION_ID=6.8.2-build.30
Distro variant:           VARIANT="Docker"
Hostname:                 machinepulse-15387795
------------------------------------------------------------

Hardware info
------------------------------------------------------------
HW model:                 Toradex Verdin AM62 WB on Verdin Development Board
Toradex version:          0075 V1.1C
Serial number:            15387795
Processor arch:           aarch64
------------------------------------------------------------

Hi, I’m the Toradex AI Assistant.

I might make mistakes. Our support team will step in if needed. If I answered your question, please tick the “Solution” checkbox. For follow-up questions to me, please use @ToradexAI in your post.

Did you like my answer? :+1: :-1:


Hello! Thank you for the detailed description and information about your setup. I understand you’re working with RS-485 on the Verdin AM62 (Ivy Board) using TorizonCore and running into “connection timed out” and CRC errors when using mbpoll with both /dev/ttyS2 and /dev/verdin-uart2. Let’s go step by step to troubleshoot and address your situation.


1. Device Tree Overlay – Syntax and Application

Your device tree overlay looks correct for enabling RS-485 on UART2. Just as a reminder, it should enable RS-485 at boot and ensure RTS line handling:

/dts-v1/;
/plugin/;

/ {
    compatible = "toradex,verdin-am62", "ti,am625";
};

&main_uart2 {
    linux,rs485-enabled-at-boot-time;
    rs485-rts-active-high;
    rs485-rts-delay = <1 1>;
    status = "okay";
};
  • Make sure the overlay is properly built into a .dtbo with TorizonCore Builder and placed in your TorizonCore customization.

Resource: Device Tree Overlays Overview

2. Console on UART2

You’ve already changed the console from ttyS2 to tty1 (now see console=tty1 in your kernel command line). That’s good, as sharing the console and RS-485 on the same UART leads to conflicts.

3. RS-485 Physical Layer Considerations

  • Double-check your Ivy Board’s J6 connector pinout, ensuring that the RS-485 A/B lines are correctly wired.
  • Make sure there’s proper termination and biasing on the RS-485 bus if your setup is not already providing this (sometimes addressed on the carrier board).
  • Ensure only one node is the master on the Modbus RTU bus.

4. Confirm the Overlay Is Active

You can check if the overlay is active in your running system by examining:

dmesg | grep -i uart
cat /proc/device-tree/soc/*uart2*/status
cat /proc/device-tree/soc/*uart2*/linux,rs485-enabled-at-boot-time

Or view the loaded overlays:

cat /sys/kernel/config/device-tree/overlays/*

This will confirm that the overlay is loaded and RS-485 is in effect.

5. Check the UART Node Name

On Verdin AM62, the Linux device for UART2 is usually /dev/ttyS2, and /dev/verdin-uart2 is a symlink for compatibility. Either should work and both refer to the same underlying device.

6. User Permissions

If running mbpoll outside a privileged container or as a user without serial access, ensure your user is a member of the dialout group or the equivalent.

ls -l /dev/ttyS2

7. Additional Parameters to Try

  • Confirm that your RS-485 slave device is properly terminated and powered.
  • Check your baud rate, parity, and all modbus settings: mismatches are a common cause of CRC errors.
  • Try a different, lower baud rate to rule out cable or termination issues.

8. Inspect Kernel Logs

After a test mbpoll run, inspect the kernel logs for UART activity or errors:

dmesg | tail

9. Wiring and RS-485 Direction

Your overlay sets rs485-rts-active-high;. Some RS-485 transceivers may require active-low instead, depending on how DE/RE (driver enable/receive enable) are wired. If unsure, you can try toggling this setting by removing or commenting the rs485-rts-active-high; property (the default is active low).

10. Example Modbus RTU Test

Here is a typical mbpoll command for an RTU slave address 1, reading 2 holding registers at baud 9600:

mbpoll -a 1 -b 9600 -P none -t 3:hex -r 1 -c 2 /dev/ttyS2
  • Adjust parameters for your specific slave configuration.

11. Reference Links


Summary of next steps:

  1. Verify overlay is loaded and active (see device tree files).
  2. Double-check wiring and bus termination.
  3. Experiment with rs485-rts-active-high/low settings.
  4. Confirm UART parameters (baud, parity, etc.) match on both ends.
  5. Check kernel logs for UART errors.

If you need a more specific device tree overlay or want to share your latest logs/config, let me know!

Best regards,
Toradex AI Assistant.

Device Tree Overlays Overview
TorizonCore Builder Device Tree Customization
UART and Serial Ports on Verdin AM62
RS-485 Usage Linux

@ToradexAI

  1. Your commands for verifying the device tree didn’t seem to work so I could not verify, though the AUX1 light lighting up tells me it is likely that the device tree is loaded.
  2. Wiring and bus termination should be fine, there is a chance I wired into the Ivy Board wrong but I checked the data sheet pinout and confirmed termination resistors with a multimeter so I believe the wiring is correct.
  3. I haven’t changed these, to my knowledge it should be high.
  4. UART parameters are correct on both ends.
  5. Kernel logs do not seem to show any errors:
torizon@machinepulse-15387795:~$ dmesg | tail
[ 1637.817186] audit: type=1327 audit(1751552913.539:246): proctitle=2F7573722F7362696E2F69707461626C6573002D2D77616974002D74006E6174002D4600444F434B4552
[ 1637.823258] audit: type=1325 audit(1751552913.539:247): table=nat family=2 entries=9 op=xt_replace pid=32852 comm="iptables"
[ 1655.465954] kauditd_printk_skb: 107 callbacks suppressed
[ 1655.465978] audit: type=1334 audit(1751552931.189:283): prog-id=45 op=LOAD
[ 1655.467669] audit: type=1334 audit(1751552931.189:284): prog-id=46 op=LOAD
[ 1686.396207] audit: type=1334 audit(1751552962.119:285): prog-id=46 op=UNLOAD
[ 1686.396250] audit: type=1334 audit(1751552962.119:286): prog-id=45 op=UNLOAD
[ 1778.189297] audit: type=1006 audit(1751553053.909:287): pid=35970 uid=0 old-auid=4294967295 auid=1000 tty=(none) old-ses=4294967295 ses=11 res=1
[ 1778.189342] audit: type=1300 audit(1751553053.909:287): arch=c00000b7 syscall=64 success=yes exit=4 a0=7 a1=ffffd55f29c0 a2=4 a3=0 items=0 ppid=1 pid=35970 auid=1000 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=(none) ses=11 comm="sshd" exe="/usr/sbin/sshd" key=(null)
[ 1778.189357] audit: type=1327 audit(1751553053.909:287): proctitle=737368643A20746F72697A6F6E205B707269765D

I have tried to troubleshoot as much as I can, to my knowledge everything is set up correctly and should work.

Hey, @TWatson!

We started with the port /dev/ttyS2, but also tried port /dev/verdin-uart2.

Trying mbpoll again both on ttyS2 and verdin-uart2 lead to getting a connection timed out error every time. Looking into this more we noticed that ttyS2 was being used by the console, so we added a kernel argument to have the console use tty1.

This is just a guess, but did you check if ttyS2 is the corresponding name for verdin-uart2? The file name numbers do not necessarily match. Try running ls -l /dev/verdin-uart* on your board, it’ll show the corresponding BSP names for all UART interfaces.

Also, try verifying again if your custom overlay was applied. You should look into the file /sysroot/boot/ostree/torizon-*/dtb/overlays.txt. Your .dtbo file should be at /sysroot/boot/ostree/torizon-*/dtb/overlays/.

cat /sysroot/boot/ostree/torizon-*/dtb/overlays.txt # Should include your dtbo file

I’ll try investigating further and update you if I find out any further information.

Best regards,

Hello @leonardo.costa.tx
Thank you for your reply, yes verdin-uart2 is actually mapped to ttyS1, but we have also tried that port. Running that command for the overlay gives this result:
torizon@machinepulse-15387795:~$ cat /sysroot/boot/ostree/torizon-*/dtb/overlays.txt
fdt_overlays=verdin-am62_dsi-to-hdmi_overlay.dtbo verdin-am62_spidev_overlay.dtbo verdin-am62-rs485-uart2.dtbo custom-kargs_overlay.dtbo

The content of the verdin-am62-rs485-uart2.dtbo overlay has changed since last time, it is now this:
/dts-v1/;
/plugin/;

/* Verdin UART_2 */
&wkup_uart0 {
linux,rs485-enabled-at-boot-time;
rs485-rts-active-low;
status = “okay”;
};

I dont think it is much of an improvement, but that is the current state of things.

Thank you again for your response

Some more info just from continued testing, I have followed the following pinout to connect the Ivy Boards RS232 and RS485 interfaces together:
RS485_P → 500 Ω Resistor → RS485_GND
RS485_N → 500 Ω Resistor → RS232_RX
RS485_N → 500 Ω Resistor → RS232_TX

Using this set up I have successfully sent and received messages from the RS485 interface to the RS232 interface and vice versa, so both interfaces are at least on and working, and this was with no device tree overlay enabled. I added back in the device tree overlay previously shown and that set up still worked. I used the pyserial library to send a couple raw byte messages to the modbus device I connected to. In both cases device overlay and no device overlay the only thing I get back is what I sent. There could be an issue with the modbus device I am connecting to, so it’s possible that is a problem, but would receiving back what I am sending also cause a problem with attempting to read Modbus data and cause the packet size being wrong? What would I change in the device tree or what commands would I run to disable that?

Hey @TWatson,

I’m a bit confused about your setup, can you tell me a bit more about it?

RS485_P → 500 Ω Resistor → RS485_GND
RS485_N → 500 Ω Resistor → RS232_RX
RS485_N → 500 Ω Resistor → RS232_TX

You said you successfully communicated both interfaces, but both RX (receive) and TX (transmit) are connected to RS485’s negative signal. Since the signals are equal, this means that the RS232 device will always send back what was sent to it. Are you also connecting the RS485 to your modbus this way? If you want to connect a RS232 device to the RS485 interface, you should use a RS485 to RS232 converter.

Also, can you tell me more about the modbus device you are connecting to the Ivy?

  • How are you connecting the signals?
  • What modbus device is it? What data are you sending to test it and what are you expecting to get back?

As a sidenote, you said you’re using an Ivy carrier board, right? In that case, you don’t need to use an overlay if you enable the Ivy device tree (k3-am625-verdin-wifi-ivy.dts). The Verdin AM62 automatically boots with the Verdin Development Board device tree (k3-am625-verdin-wifi-dev.dts) enabled, since it can’t detect what carrier board it’s on. You can use the fw-utils to change the fdtfile U-Boot variable to the Ivy device tree.

sudo fw_setenv fdtfile 'imx6q-apalis-ixora-v1.1.dtb'

Best regards,

Yeah sorry if that last message was confusing. That resistor set up was purely to test, it plugged the RS232 of the Ivy Board into the RS485 on the Ivy Board. I was able to successfully send and receive messages from one interface to other, for example. I could do echo “Test” > /dev/verdin-uart1 and see the “Test” doing cat /dev/verdin-uart2 and then vice versa. That is not our use case however, just a debug step to confirm that both interfaces were enabled and successfully sending and receiving data, which they are.

As far as our actual setup we want to be able to receive Modbus RTU data over RS485. To test this I am using pymodbus to attempt to read a holding register on /dev/verdin-uart2. I get an error using pymodbus saying that the data wouldn’t fit in 4 bytes (I was trying to read 2 registers). Testing with pyserial shows that I receive back every message I send over serial, which is what is causing problems with pymodbus I believe.

I believe the device tree likely never had anything to do with it and was just a rabbit hole I went down, as one of my debugging steps was plugging the RS485 interfaces of 2 Ivy Boards together and I had no problem sending data back and forth. More than likely my main issues are that pymodbus cannot work if I receive the data I send, and I am probably not wired into my RS485 port on my modbus device correctly.

So just to follow up on this, we ended up getting everything working, the main problem is the loopback on the Ivy board which I could not find a software solution to work around. After confirming that the modbus device was wired correctly I realized my problem was with how I was constructing the Modbus CRC bytes, after fixing that I could send and receive Modbus frames no issues. It seems we cannot use the normal modbus serial libraries because of the loopback however, if there is a software way to disable that, or even if there is a way to disregard the loopback bytes we receive outside of programming so that the modbus libraries can work that would be great. If not though it will not be too much work to program it manually, so this problem can be considered solved

Hey, @TWatson,

I saw that you marked the issue as solved, but I investigated a bit further, and hopefully something here will be useful to you.

I investigated a bit further, and what is probably going on is that, due to RS485 being a half-duplex communication protocol, the UART ↔ RS485 converter in the Ivy carrier board always reads the sent data, producing the “echo” you were seeing. The Ivy Carrier Board does not have the feature to disable the RS485 receive via hardware, and we currently don’t have plans to add it (although other Verdin carrier boards support it. Check their datasheets for further details).

For your use case, as you described, the echo needs to be suppressed via software. I looked into the library you’re using and found this patch, which was merged in October 2024. Maybe you were using an out of date version? Or maybe using a different function for reading the data? I don’t know exactly how you’re implementing your application, but hopefully this helps.

Let me know if I can help any further.

Best regards,

Hey Leonardo,
Thank you for that tip! Sadly we shifted away from pymodbus, I was just using it to test data transfer, we are using NModbus which is in C#, and it doesn’t appear to support the same thing from my quick look. It still shouldn’t be an issue as the protocol is relatively easy to work with the raw values. Thank you for your help!

1 Like