UART1 RTS active-low imx6dl BSP 6.5.0 / imx7 BSP 6.6.0

Hello,

I have been working with BSP 6.5.0 upstream reference image on iMX6DL colibri.

I am trying to use UART1 with RS485 mode and rts-active-low.

If I use the following dts overlay the kernel won’t boot.
Uboot is able to load the dts and apply the overlays without errors, then the last message on the console is “Starting kernel …”


&iomuxc {

   pinctrl_uart1_my: uart1grp-my {
        fsl,pins = <
            MX6QDL_PAD_CSI0_DAT10__UART1_RX_DATA 0x1b0b1
            MX6QDL_PAD_CSI0_DAT11__UART1_TX_DATA 0x1b0b1
            MX6QDL_PAD_EIM_D19__UART1_RTS_B 0x1b0b1
            MX6QDL_PAD_EIM_D20__UART1_CTS_B 0x1b0b1
        >;
   };
};

&uart1 {
    pinctrl-0 = <&pinctrl_uart1_my>;
    uart-has-rtscts;
    rs485-rts-active-low;
    linux,rs485-enabled-at-boot-time;
    rs485-rts-delay = <0 0>;
    fsl,dte-mode;
    status = "okay";
};

If I comment out the property “rs485-rts-active-low”, the kernel boots, then by configuring the RTS in user space with ioctl (code snippet below), the serial port works fine.

struct serial_rs485 rs485conf;

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

rs485conf.flags &= ~(SER_RS485_RTS_ON_SEND);
rs485conf.flags |= SER_RS485_RTS_AFTER_SEND;


if (ioctl (fd, TIOCSRS485, &rs485conf) < 0) {
...
}

Additional tests:

  • Using the equivalent dts configuration with BSP 6.5.0 and a colibri iMX7D 1G emmc there is no problem
  • Using BSP 6.6.0 and a colibri imx7 1G emmc the same problem shows up.

Am I missing something?

regards

f

As a test, can you insert a rs485-rx-during-tx into the dts and see if things work with the rs485-rts-active-low also enabled?

thanks for your quick reply.

I have tried adding “rs485-rx-during-tx” in the dts with the following configurations:

  • iMX6DL + BSP 6.5.0
  • iMX7D 1G emmc + BSP 6.6.0

The kernel still won’t boot in both cases.

Thanks

f

Bummer…it was a shot in the dark really. I don’t work with any of your modules, so to summarize:

BSP 6.5.0 and a colibri iMX7D 1G emmc - Works
BSP 6.6.0 and a colibri iMX7D 1G emmc - Doesn’t work
iMX6DL - Nothing works

Those first two suggest something between kernel releases. I guess I’d focus there looking at diffs, etc., for the serial stuff.

The third suggests something with the rts line perhaps being used somewhere else in a dts?

Hopefully someone from toradex has some hardware and can do a quick check on their side.

I know…not much help. Good luck!

Hello @elfranzo,

Thanks for reporting this issue!
Also thanks @DaveM for helping in the meantime!
I will try to reproduce this issue and will get back to you as soon as I have an update on the matter. Thanks for understanding!

@DaveM It was worth a try, Thanks anyway.

Actually I still haven’t tried iMX6DL + BSP 6.6.0.

I agree with you, there should have been some changes between BSP 6.5.0 and BSP 6.6.0 for iMX7D while, for iMX6DL probably there is also something else.

@rudhi.tx , thanks! when the feature is enabled after the system has been booted, the serial port works fine. Maybe I am wrong, but this suggests some kind of complex interaction at boot time.

Additional infos:

------------------------------------------------------------
Bootloader:               U-Boot
Kernel version:           6.1.83+git.e5cd595e23c1 #1 SMP Tue Mar 26 22:22:57 UTC 2024
Kernel command line:      root=PARTUUID=ed0b8080-02 ro rootwait console=tty1 console=ttymxc4,115200n8 consoleblank=0
Distro name:              NAME="TDX Wayland with XWayland Upstream"
Distro version:           VERSION_ID=6.6.0-build.12
Distro variant:           -
Hostname:                 colibri-imx7-emmc-06373028
------------------------------------------------------------

Hardware info
------------------------------------------------------------
HW model:                 Toradex Colibri iMX7D 1GB (eMMC) on Colibri Evaluation Board V3
Toradex version:          0039 V1.1A
Serial number:            06373028
Processor arch:           armv7l
------------------------------------------------------------

DTS overlay:

&iomuxc {


   pinctrl_uart1_es1007b: uart1grp-es1007b {
        fsl,pins = <
             MX7D_PAD_UART1_TX_DATA__UART1_DTE_RX 0x79
             MX7D_PAD_UART1_RX_DATA__UART1_DTE_TX 0x79
             MX7D_PAD_SAI2_TX_SYNC__UART1_DTE_RTS    0x79
             MX7D_PAD_SAI2_TX_BCLK__UART1_DTE_CTS    0x79

        >;
   };

};

&uart1 {
   
    pinctrl-0 = <&pinctrl_uart1_es1007b>;
    assigned-clocks = <&clks IMX7D_UART1_ROOT_SRC>;
    assigned-clock-parents = <&clks IMX7D_OSC_24M_CLK>;
    
    uart-has-rtscts;
    rs485-rts-active-low;
   
    linux,rs485-enabled-at-boot-time;
    rs485-rts-delay = <0 0>;
    fsl,dte-mode;
    status = "okay";
};

I have tried a quick diff of the two kernel sources and the only notable difference in imx.c is:

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=6e04a9d30509fb53ba6df5d655ed61d607a7cfda

I don’t know if this can in any way be related to my issue

thanks again

f

I wonder if changing to a gpios scheme for rts/cts makes any difference? Then changing the dts for that kind of control?

That is another odd scenario: I was able to use rts-gpios on UART2 but not on UART1, but this could depend on the fact that the two serial ports have some hw differences on my carrier, or maybe I am doing something wrong. If it worked it could be a nice workaround. A dirtier one is to change the rs485conf flag with a script during system init.

After some more tests, I noticed that you can see this behavior also on UART2 (I tried this with imx7d + bsp 6.6.0)
It the dts contains the combination of uart-has-rtscts + rs485-rts-active-low, the colibri won’t boot even if it is located on a iris board, so this also rules out hw differences.

Does the kernel startup offer any interesting text in DEBUG mode? Sometimes the drivers give a bit of information when startup issues arise even in a working scenario.

I am still working with the BSP reference image from Toradex.
Is it possible to enable more debug messages without recompiling the kernel?

You can start by pasting the output of ‘dmesg’ here during a “good” and “bad” boot (ya, I know the bad boot is a lockup, but just being complete :wink:

Ok thanks to your hint I tried something I hadn’t tried before.
I set up the console on ttymxc1 so I managed to see what happens during the bad boot.

As you can see below rcu_sched detects a CPU stall.
This happens just after serial setup and a message from imx-uart

[ 0.259892] imx-uart 30860000.serial: low-active RTS not possible when receiver is off, enabling receiver

[    0.000000] Booting Linux on physical CPU 0x0
[    0.000000] Linux version 6.1.83+git.e5cd595e23c1 (oe-user@oe-host) (arm-tdx-linux-gnueabi-gcc (GCC) 11.4.0, GNU 4
[    0.000000] CPU: ARMv7 Processor [410fc075] revision 5 (ARMv7), cr=10c5387d
[    0.000000] CPU: div instructions available: patching division code
[    0.000000] CPU: PIPT / VIPT nonaliasing data cache, VIPT aliasing instruction cache
[    0.000000] OF: fdt: Machine model: Toradex Colibri iMX7D 1GB (eMMC) on Colibri Evaluation Board V3
[    0.000000] Memory policy: Data cache writealloc
[    0.000000] cma: Reserved 256 MiB at 0xb0000000
[    0.000000] Zone ranges:
[    0.000000]   Normal   [mem 0x0000000080000000-0x00000000afffffff]
[    0.000000]   HighMem  [mem 0x00000000b0000000-0x00000000bfffffff]
[    0.000000] Movable zone start for each node
[    0.000000] Early memory node ranges
[    0.000000]   node   0: [mem 0x0000000080000000-0x00000000bfffffff]
[    0.000000] Initmem setup node 0 [mem 0x0000000080000000-0x00000000bfffffff]
[    0.000000] psci: probing for conduit method from DT.
[    0.000000] psci: PSCIv1.0 detected in firmware.
[    0.000000] psci: Using standard PSCI v0.2 function IDs
[    0.000000] psci: Trusted OS migration not required
[    0.000000] psci: SMC Calling Convention v1.0
[    0.000000] percpu: Embedded 13 pages/cpu s21908 r8192 d23148 u53248
[    0.000000] Built 1 zonelists, mobility grouping on.  Total pages: 260608
[    0.000000] Kernel command line: root=PARTUUID=ed0b8080-02 ro rootwait console=tty1 console=ttymxc1,115200n8 cons0
[    0.000000] Dentry cache hash table entries: 131072 (order: 7, 524288 bytes, linear)
[    0.000000] Inode-cache hash table entries: 65536 (order: 6, 262144 bytes, linear)
[    0.000000] mem auto-init: stack:off, heap alloc:off, heap free:off
[    0.000000] Memory: 758052K/1048576K available (11264K kernel code, 1238K rwdata, 3900K rodata, 1024K init, 438K )
[    0.000000] SLUB: HWalign=64, Order=0-3, MinObjects=0, CPUs=2, Nodes=1
[    0.000000] rcu: Hierarchical RCU implementation.
[    0.000000] rcu:     RCU event tracing is enabled.
[    0.000000] rcu:     RCU restricting CPUs from NR_CPUS=4 to nr_cpu_ids=2.
[    0.000000]  Tracing variant of Tasks RCU enabled.
[    0.000000] rcu: RCU calculated value of scheduler-enlistment delay is 10 jiffies.
[    0.000000] rcu: Adjusting geometry for rcu_fanout_leaf=16, nr_cpu_ids=2
[    0.000000] NR_IRQS: 16, nr_irqs: 16, preallocated irqs: 16
[    0.000000] GIC: Using split EOI/Deactivate mode
[    0.000000] rcu: srcu_init: Setting srcu_struct sizes based on contention.
[    0.000000] arch_timer: cp15 timer(s) running at 8.00MHz (phys).
[    0.000000] clocksource: arch_sys_counter: mask: 0xffffffffffffff max_cycles: 0x1d854df40, max_idle_ns: 440795202s
[    0.000002] sched_clock: 56 bits at 8MHz, resolution 125ns, wraps every 2199023255500ns
[    0.000018] Switching to timer-based delay loop, resolution 125ns
[    0.000471] Switching to timer-based delay loop, resolution 41ns
[    0.000486] sched_clock: 32 bits at 24MHz, resolution 41ns, wraps every 89478484971ns
[    0.000512] clocksource: mxc_timer1: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 79635851949 ns
[    0.002115] Console: colour dummy device 80x30
[    0.002685] printk: console [tty1] enabled
[    0.002740] Calibrating delay loop (skipped), value calculated using timer frequency.. 48.00 BogoMIPS (lpj=240000)
[    0.002781] CPU: Testing write buffer coherency: ok
[    0.002852] pid_max: default: 32768 minimum: 301
[    0.003072] Mount-cache hash table entries: 2048 (order: 1, 8192 bytes, linear)
[    0.003116] Mountpoint-cache hash table entries: 2048 (order: 1, 8192 bytes, linear)
[    0.004248] CPU0: update cpu_capacity 1024
[    0.004288] CPU0: thread -1, cpu 0, socket 0, mpidr 80000000
[    0.005348] cblist_init_generic: Setting adjustable number of callback queues.
[    0.005388] cblist_init_generic: Setting shift to 1 and lim to 1.
[    0.005564] Setting up static identity map for 0x80100000 - 0x80100078
[    0.005745] rcu: Hierarchical SRCU implementation.
[    0.005769] rcu:     Max phase no-delay instances is 1000.
[    0.007221] smp: Bringing up secondary CPUs ...
[    0.008263] CPU1: update cpu_capacity 1024
[    0.008276] CPU1: thread -1, cpu 1, socket 0, mpidr 80000001
[    0.008427] smp: Brought up 1 node, 2 CPUs
[    0.008487] SMP: Total of 2 processors activated (96.00 BogoMIPS).
[    0.008511] CPU: All CPU(s) started in HYP mode.
[    0.008527] CPU: Virtualization extensions available.
[    0.009204] devtmpfs: initialized
[    0.020573] VFP support v0.3: implementor 41 architecture 2 part 30 variant 7 rev 5
[    0.020878] clocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 19112604462750000 ns
[    0.020928] futex hash table entries: 512 (order: 3, 32768 bytes, linear)
[    0.031201] pinctrl core: initialized pinctrl subsystem
[    0.033222] NET: Registered PF_NETLINK/PF_ROUTE protocol family
[    0.039870] DMA: preallocated 256 KiB pool for atomic coherent allocations
[    0.041369] thermal_sys: Registered thermal governor 'step_wise'
[    0.041466] cpuidle: using governor menu
[    0.042138] hw-breakpoint: found 5 (+1 reserved) breakpoint and 4 watchpoint registers.
[    0.042184] hw-breakpoint: maximum watchpoint size is 8 bytes.
[    0.049018] platform soc: Fixed dependency cycle(s) with /soc/bus@30000000/gpc@303a0000
[    0.051494] platform 302c0000.pinctrl: Fixed dependency cycle(s) with /soc/bus@30000000/pinctrl@302c0000/gpiolpsrp
[    0.051749] imx7d-pinctrl 302c0000.pinctrl: initialized IMX pinctrl driver
[    0.052369] platform 30330000.pinctrl: Fixed dependency cycle(s) with /soc/bus@30000000/pinctrl@30330000/gpio4grp
[    0.052425] platform 30330000.pinctrl: Fixed dependency cycle(s) with /soc/bus@30000000/pinctrl@30330000/gpio3grp
[    0.052472] platform 30330000.pinctrl: Fixed dependency cycle(s) with /soc/bus@30000000/pinctrl@30330000/gpio2grp
[    0.052517] platform 30330000.pinctrl: Fixed dependency cycle(s) with /soc/bus@30000000/pinctrl@30330000/gpio1grp
[    0.053194] imx7d-pinctrl 30330000.pinctrl: initialized IMX pinctrl driver
[    0.065312] platform 30730000.lcdif: Fixed dependency cycle(s) with /panel-dpi
[    0.065450] platform panel-dpi: Fixed dependency cycle(s) with /soc/bus@30400000/lcdif@30730000
[    0.078725] kprobes: kprobe jump-optimization is enabled. All kprobes are optimized if possible.
[    0.095747] SCSI subsystem initialized
[    0.096139] usbcore: registered new interface driver usbfs
[    0.096215] usbcore: registered new interface driver hub
[    0.096293] usbcore: registered new device driver usb
[    0.096451] usb_phy_generic usbphynop1: supply vcc not found, using dummy regulator
[    0.096638] usb_phy_generic usbphynop1: dummy supplies not allowed for exclusive requests
[    0.096679] usb_phy_generic usbphynop1: dummy supplies not allowed for exclusive requests
[    0.097000] usb_phy_generic usbphynop2: supply vcc not found, using dummy regulator
[    0.097188] usb_phy_generic usbphynop2: dummy supplies not allowed for exclusive requests
[    0.097228] usb_phy_generic usbphynop2: dummy supplies not allowed for exclusive requests
[    0.099122] i2c i2c-0: IMX I2C adapter registered
[    0.100795] i2c i2c-3: IMX I2C adapter registered
[    0.101137] mc: Linux media interface: v0.10
[    0.101230] videodev: Linux video capture interface: v2.00
[    0.101360] pps_core: LinuxPPS API ver. 1 registered
[    0.101383] pps_core: Software ver. 5.3.6 - Copyright 2005-2007 Rodolfo Giometti <giometti@linux.it>
[    0.101427] PTP clock support registered
[    0.102107] Advanced Linux Sound Architecture Driver Initialized.
[    0.102959] Bluetooth: Core ver 2.22
[    0.103031] NET: Registered PF_BLUETOOTH protocol family
[    0.103055] Bluetooth: HCI device and connection manager initialized
[    0.103082] Bluetooth: HCI socket layer initialized
[    0.103107] Bluetooth: L2CAP socket layer initialized
[    0.103143] Bluetooth: SCO socket layer initialized
[    0.103901] clocksource: Switched to clocksource arch_sys_counter
[    0.104241] VFS: Disk quotas dquot_6.6.0
[    0.104330] VFS: Dquot-cache hash table entries: 1024 (order 0, 4096 bytes)
[    0.116108] NET: Registered PF_INET protocol family
[    0.116507] IP idents hash table entries: 16384 (order: 5, 131072 bytes, linear)
[    0.119259] tcp_listen_portaddr_hash hash table entries: 512 (order: 0, 4096 bytes, linear)
[    0.119324] Table-perturb hash table entries: 65536 (order: 6, 262144 bytes, linear)
[    0.119361] TCP established hash table entries: 8192 (order: 3, 32768 bytes, linear)
[    0.119469] TCP bind hash table entries: 8192 (order: 5, 131072 bytes, linear)
[    0.119745] TCP: Hash tables configured (established 8192 bind 8192)
[    0.119890] UDP hash table entries: 512 (order: 2, 16384 bytes, linear)
[    0.119974] UDP-Lite hash table entries: 512 (order: 2, 16384 bytes, linear)
[    0.120217] NET: Registered PF_UNIX/PF_LOCAL protocol family
[    0.120860] RPC: Registered named UNIX socket transport module.
[    0.120898] RPC: Registered udp transport module.
[    0.120917] RPC: Registered tcp transport module.
[    0.120934] RPC: Registered tcp NFSv4.1 backchannel transport module.
[    0.120962] PCI: CLS 0 bytes, default 64
[    0.122192] hw perfevents: enabled with armv7_cortex_a7 PMU driver, 5 counters available
[    0.123766] Initialise system trusted keyrings
[    0.124126] workingset: timestamp_bits=30 max_order=18 bucket_order=0
[    0.130200] NFS: Registering the id_resolver key type
[    0.130354] Key type id_resolver registered
[    0.130375] Key type id_legacy registered
[    0.130480] nfs4filelayout_init: NFSv4 File Layout Driver Registering...
[    0.130508] nfs4flexfilelayout_init: NFSv4 Flexfile Layout Driver Registering...
[    0.248382] Key type asymmetric registered
[    0.248418] Asymmetric key parser 'x509' registered
[    0.248623] bounce: pool size: 64 pages
[    0.248735] io scheduler mq-deadline registered
[    0.248761] io scheduler kyber registered
[    0.255500] mxs-dma 33000000.dma-controller: initialized
[    0.259892] imx-uart 30860000.serial: low-active RTS not possible when receiver is off, enabling receiver
[    0.260015] 30860000.serial: ttymxc0 at MMIO 0x30860000 (irq = 271, base_baud = 1500000) is a IMX
[    0.261109] 30890000.serial: ttymxc1 at MMIO 0x30890000 (irq = 272, base_baud = 1500000) is a IMX
[    1.193318] printk: console [ttymxc1] enabled
[    1.198704] 30880000.serial: ttymxc2 at MMIO 0x30880000 (irq = 273, base_baud = 1500000) is a IMX
[    1.208560] 30a70000.serial: ttymxc4 at MMIO 0x30a70000 (irq = 274, base_baud = 1500000) is a IMX
[    1.226559] Stack Depot allocating hash table of 65536 entries with kvcalloc
[   21.273891] rcu: INFO: rcu_sched detected stalls on CPUs/tasks:
[   21.279848] rcu:     0-....: (13 ticks this GP) idle=067c/0/0x1 softirq=15/17 fqs=1050
[   21.287532]  (detected by 1, t=2102 jiffies, g=-1183, q=29 ncpus=2)
[   21.293818] Sending NMI from CPU 1 to CPUs 0:
[   21.298193] NMI backtrace for cpu 0
[   21.298207] CPU: 0 PID: 0 Comm: swapper/0 Not tainted 6.1.83+git.e5cd595e23c1 #1
[   21.298219] Hardware name: Freescale i.MX7 Dual (Device Tree)
[   21.298228] PC is at arch_cpu_idle+0x30/0x3c
[   21.298266] LR is at arch_cpu_idle+0x2c/0x3c
[   21.298282] pc : [<c0108260>]    lr : [<c010825c>]    psr: 60000013
[   21.298289] sp : c1201f48  ip : 00000000  fp : c1205068
[   21.298297] r10: c1165cb0  r9 : 00000000  r8 : 00000000
[   21.298303] r7 : c120505c  r6 : c1205010  r5 : 00000000  r4 : c1208a40
[   21.298311] r3 : c0119740  r2 : 00000000  r1 : 00000679  r0 : 00000005
[   21.298320] Flags: nZCv  IRQs on  FIQs on  Mode SVC_32  ISA ARM  Segment none
[   21.298331] Control: 10c5387d  Table: 8000406a  DAC: 00000051
[   21.298364]  arch_cpu_idle from default_idle_call+0x24/0x34
[   21.298400]  default_idle_call from do_idle+0x1ec/0x2a8
[   21.298424]  do_idle from cpu_startup_entry+0x28/0x2c
[   21.298440]  cpu_startup_entry from rest_init+0x90/0xac
[   21.298467]  rest_init from arch_post_acpi_subsys_init+0x0/0x8

I think you probably need to really try and figure out why you can’t use gpios for your rs-485 rts control for uart1. Using “built-in” control is fraught with peril :wink:

Hi @DaveM,

I try to focus on the iMX6DL + BSP6.5.0 + UART_A because this was the intial question. I think this is not something you should do. The problem is that UART_A is used as debug output for Linux on the iMX6, if you use it in RS485 mode then the kernel expects to have a RS485 transceiver. If the CTS pin is not going to the right level, the driver will not be allowed to send data.
Why do you have to use UART_A for RS485? Can’t you use UART_B instead?

I would strongly advise to not use the debug console for anything else than logging, if you have to do it anyway then have a look at this article:

Please note that also U-Boot is using it for logging, so you have to deal with this as well!

Regards,
Stefan

Hi @stefan_e.tx , I wasn’t the OP…it was @elfranzo . But I agree with you regarding uart_a :wink:

Sorry @DaveM and thanks a lot for addressing @elfranzo as well as for your help :slight_smile:

1 Like

Hi @stefan_e.tx,
thanks for your reply.
The custom board where the colibri is used has 2 RS 485 on UART_A and UART_B.
Probably it was a poor choice, (not mine) I am “simply” trying to upgrade the system to a new bsp, and changing the hw is not an option on the table.

I know that the default image uses UART_A as the debug console. I have taken care of it by changing the uboot variable, setting the console to a different serial port, so this should not be a problem.

Currently I am working with imx6 and imx7 with BSP 6.6. As I said these setups show the issue too.
I managed to find a workaround to this problem.
During the boot I run a program that sets the RTS to “active low” using ioctl . That’s not very elegant but it works: the system boots up, the serial ports work in rs485 mode.
I still don’t understand why the kernel hangs if I try to do that using the dts.

regards

Hi @elfranzo

I’m not sure if I understand the setup completely which makes it hard to reproduce. Can you reproduce the issue with a Toradex Board? I tried to do the device tree changes on UART_B on the Colibri iMX6DL and it worked there. As said UART_A is the debug UART and can cause issues as long as it stays active. However, if you can give an example of how you disable it together with an example of how we can reproduce the issue on a Toradex board we can proceed with analyzing it.

Regards,
Stefan

Thanks again @stefan_e.tx
I apologize for being unclear. As a matter of fact I tried different setups.

I think you can reproduce the problem by using a colibri imx6 or imx7 with a iris board + bsp 6.6

The issue is about UART_A, but if we rule it out because it must not be used in any way but as debug console, we can close the case. As I said I have a workaround now.

On the other hand, if you think it could be useful to further investigate, you should see that the system hangs during boot by setting UART_A in rs485mode AND setting rs485-rts-active-low. If you don’t add the active low option the kernel boots just fine.

I know that I cannot test the serial port with the iris board since it doesn’t have rs485 transceivers, anyway I expected that system could at least boot.

In order to have more details about what happened at boot time, I switched the kernel debug console to UART_B. You can see the log in one of the previous messages.

Regards

Hi @elfanzo

Sorry for the late answer. I was able to reproduce your issue, the following patch was sent upstream and should fix it:
https://lore.kernel.org/linux-serial/20240621153829.183780-1-eichest@gmail.com/T/#u
If you have time it would be great if you could apply the patch to your setup and see if the issue is gone.

Regards,
Stefan