rasp14
Posts: 182
Joined: Sun Jun 22, 2014 2:49 pm

Possible to Assign Static Device Name to UART?

Tue Oct 03, 2023 6:28 am

I'm currently using config.txt to enable uart4 and uart5 using config below:

Code: Select all

[all]
dtoverlay=uart4
dtoverlay=uart5
Both ports are able to work properly. However there is one small issue. The device name under path /dev/ is not static. In my machine, I'm getting device name below:

Code: Select all

pi@raspberry:/ $ ls -lah /dev/ttyAMA*
crw-rw---- 1 root dialout 204, 64 Oct  2 06:07 /dev/ttyAMA0
crw-rw---- 1 root dialout 204, 65 Oct  3 05:35 /dev/ttyAMA1
crw-rw---- 1 root dialout 204, 66 Oct  3 05:34 /dev/ttyAMA2
/dev/ttyAMA1 and /dev/ttyAMA2 can be uart4 and uart5 respectively. However, the order could change when machine restarts.

Is there a way to set a static device name for uart4 or uart5 via config.txt or other means? Or is there a way to identify whether the device name is belong to uart4 or uart5?

Thanks in advance.

PhilE
Raspberry Pi Engineer & Forum Moderator
Raspberry Pi Engineer & Forum Moderator
Posts: 5560
Joined: Mon Sep 29, 2014 1:07 pm
Location: Cambridge

Re: Possible to Assign Static Device Name to UART?

Tue Oct 03, 2023 7:45 am

You must be running an older kernel - the current 6.1 kernels already do that, using Device Tree aliases to assign logical numbers to the UART devices. Using your example config.txt would result in /dev/ttyAMA0, /dev/ttyAMA4 and /dev/ttyAMA5.

rasp14
Posts: 182
Joined: Sun Jun 22, 2014 2:49 pm

Re: Possible to Assign Static Device Name to UART?

Tue Oct 03, 2023 7:52 am

PhilE wrote:
Tue Oct 03, 2023 7:45 am
You must be running an older kernel - the current 6.1 kernels already do that, using Device Tree aliases to assign logical numbers to the UART devices. Using your example config.txt would result in /dev/ttyAMA0, /dev/ttyAMA4 and /dev/ttyAMA5.
Got it, good to know this is fixed for newer kernel.

Currently I'm running older kernel 5.15.84-v8+. Is there any way to programmatically identify which device name belonged to uart4 or uart5?

PhilE
Raspberry Pi Engineer & Forum Moderator
Raspberry Pi Engineer & Forum Moderator
Posts: 5560
Joined: Mon Sep 29, 2014 1:07 pm
Location: Cambridge

Re: Possible to Assign Static Device Name to UART?

Tue Oct 03, 2023 8:06 am

Yes, but it's not particularly pretty - it involves rooting around in /sys/....

I've a feeling I've answered this before on the Forums, probably in the last year - I'll have a dig.

PhilE
Raspberry Pi Engineer & Forum Moderator
Raspberry Pi Engineer & Forum Moderator
Posts: 5560
Joined: Mon Sep 29, 2014 1:07 pm
Location: Cambridge

Re: Possible to Assign Static Device Name to UART?

Tue Oct 03, 2023 9:26 am

No, I can't readily find it, so I'll go through the steps required.

[ Unfortunately for you I'm running up-to-date kernels that already have the logical names, but I'll try to fake the situation you will be seeing. ]

Every UART (and tty of any kind) has an entry in /sys/class/tty/ - for /dev/ttyAMA2 that is /sys/class/tty/ttyAMA2:

Code: Select all

$ ls -l /sys/class/tty/ttyAMA2
lrwxrwxrwx 1 root root 0 Oct  3 09:14 /sys/class/tty/ttyAMA2 -> ../../devices/platform/soc/fe201a00.serial/tty/ttyAMA2
The hexadecimal address in there (fe201a00) is enough to identify that this is actually UART5, but let's proceed anyway and follow the symbolic link (note the trailing slash):

Code: Select all

$ ls -l /sys/class/tty/ttyAMA2/
total 0
-r--r--r-- 1 root root 4096 Oct  3 09:34 close_delay
-r--r--r-- 1 root root 4096 Oct  3 09:34 closing_wait
-rw-r--r-- 1 root root 4096 Oct  3 09:34 console
-r--r--r-- 1 root root 4096 Oct  3 09:34 custom_divisor
-r--r--r-- 1 root root 4096 Oct  3 09:34 dev
lrwxrwxrwx 1 root root    0 Oct  3 09:14 device -> ../../../fe201a00.serial
-r--r--r-- 1 root root 4096 Oct  3 09:34 flags
-r--r--r-- 1 root root 4096 Oct  3 09:34 iomem_base
-r--r--r-- 1 root root 4096 Oct  3 09:34 iomem_reg_shift
-r--r--r-- 1 root root 4096 Oct  3 09:34 io_type
-r--r--r-- 1 root root 4096 Oct  3 09:34 irq
-r--r--r-- 1 root root 4096 Oct  3 09:34 line
-r--r--r-- 1 root root 4096 Oct  3 09:34 port
drwxr-xr-x 2 root root    0 Oct  3 09:34 power
lrwxrwxrwx 1 root root    0 Oct  3 09:14 subsystem -> ../../../../../../class/tty
-r--r--r-- 1 root root 4096 Oct  3 09:34 type
-r--r--r-- 1 root root 4096 Oct  3 09:34 uartclk
-rw-r--r-- 1 root root 4096 Oct  3 09:14 uevent
-r--r--r-- 1 root root 4096 Oct  3 09:34 xmit_fifo_size
And now follow the device link:

Code: Select all

$ ls -l /sys/class/tty/ttyAMA2/device/
total 0
lrwxrwxrwx 1 root root    0 Oct  3 09:14 driver -> ../../../../bus/amba/drivers/uart-pl011
-rw-r--r-- 1 root root 4096 Oct  3 09:34 driver_override
-r--r--r-- 1 root root 4096 Oct  3 09:34 id
lrwxrwxrwx 1 root root    0 Oct  3 09:14 of_node -> ../../../../firmware/devicetree/base/soc/serial@7e201a00
drwxr-xr-x 2 root root    0 Oct  3 09:34 power
-r--r--r-- 1 root root 4096 Oct  3 09:34 resource
lrwxrwxrwx 1 root root    0 Oct  3 09:14 subsystem -> ../../../../bus/amba
lrwxrwxrwx 1 root root    0 Oct  3 09:34 supplier:platform:fe101000.cprman -> ../../../virtual/devlink/platform:fe101000.cprman--amba:fe201a00.serial
lrwxrwxrwx 1 root root    0 Oct  3 09:34 supplier:platform:fe200000.gpio -> ../../../virtual/devlink/platform:fe200000.gpio--amba:fe201a00.serial
drwxr-xr-x 3 root root    0 Oct  3 09:14 tty
-rw-r--r-- 1 root root 4096 Oct  3 09:14 uevent
The "of_node" symbolic link is useful because it points directly into the live Device Tree:

Code: Select all

$ readlink /sys/class/tty/ttyAMA2/device/of_node
../../../../firmware/devicetree/base/soc/serial@7e201a00
Now let's find the uart aliases in Device Tree. We tend to use "/proc/device-tree" as file system location, but it is just a symbolic link into /sys:

Code: Select all

$ ls -l /proc/device-tree
lrwxrwxrwx 1 root root 29 Oct  3 09:14 /proc/device-tree -> /sys/firmware/devicetree/base
$ ls /sys/firmware/devicetree/base/aliases/uart*
/sys/firmware/devicetree/base/aliases/uart0
/sys/firmware/devicetree/base/aliases/uart1
/sys/firmware/devicetree/base/aliases/uart2
/sys/firmware/devicetree/base/aliases/uart3
/sys/firmware/devicetree/base/aliases/uart4
/sys/firmware/devicetree/base/aliases/uart5
Ah, this is where 5.15 and 6.1 really diverge - your list probably stops at uart1, because our 5.15 kernel didn't contain a complete list of UART aliases. However, I can use my image to show what the content of each of them should be on a Pi 4:

Code: Select all

$ grep -a . /sys/firmware/devicetree/base/aliases/uart*
/sys/firmware/devicetree/base/aliases/uart0:/soc/serial@7e201000
/sys/firmware/devicetree/base/aliases/uart1:/soc/serial@7e215040
/sys/firmware/devicetree/base/aliases/uart2:/soc/serial@7e201400
/sys/firmware/devicetree/base/aliases/uart3:/soc/serial@7e201600
/sys/firmware/devicetree/base/aliases/uart4:/soc/serial@7e201800
/sys/firmware/devicetree/base/aliases/uart5:/soc/serial@7e201a00
This shows that the alias "uart5" contains the string "/soc/serial@7e201a00", which matches the end of the of_node for ttyAMA2:

Code: Select all

$ readlink /sys/class/tty/ttyAMA2/device/of_node
../../../../firmware/devicetree/base/soc/serial@7e201a00
If I was coding a conversion from tty name to UART index in bash shell I'd do something like this:

Code: Select all

ttyname="ttyAMA2" # for example
case $(readlink /sys/class/tty/$ttyname/device/of_node | cut -d@ -f2) in
    7e201000) uartidx=0;;
    7e201400) uartidx=2;;
    7e201600) uartidx=3;;
    7e201800) uartidx=4;;
    7e201a00) uartidx=5;;
esac
In C I would locate the hex number after the '@', then use the formula:

Code: Select all

uartidx = (address - 0x7e201000) / 0x200;
I hope that helps a bit.

rasp14
Posts: 182
Joined: Sun Jun 22, 2014 2:49 pm

Re: Possible to Assign Static Device Name to UART?

Wed Oct 04, 2023 2:35 am

PhilE wrote:
Tue Oct 03, 2023 9:26 am
No, I can't readily find it, so I'll go through the steps required.

[ Unfortunately for you I'm running up-to-date kernels that already have the logical names, but I'll try to fake the situation you will be seeing. ]

Every UART (and tty of any kind) has an entry in /sys/class/tty/ - ..........
Thanks mate. I'll try it on my older kernel and see if I can find the uart link to device name as you described.

User avatar
Milliways
Posts: 865
Joined: Fri Apr 25, 2014 12:18 am
Location: Sydney, Australia

Re: Possible to Assign Static Device Name to UART?

Wed Oct 04, 2023 3:01 am

PhilE wrote:
Tue Oct 03, 2023 7:45 am
You must be running an older kernel - the current 6.1 kernels already do that, using Device Tree aliases to assign logical numbers to the UART devices. Using your example config.txt would result in /dev/ttyAMA0, /dev/ttyAMA4 and /dev/ttyAMA5.
Does this work with current production kernel?
I had seem comments indicating this but maybe only in later kernels.

I am using dtoverlay=uart2 and kernel 6.1.21-v8+

I have

Code: Select all

/dev/ttyAMA0 
/dev/ttyAMA1

rasp14
Posts: 182
Joined: Sun Jun 22, 2014 2:49 pm

Re: Possible to Assign Static Device Name to UART?

Wed Oct 04, 2023 5:26 am

PhilE wrote:
Tue Oct 03, 2023 9:26 am
No, I can't readily find it, so I'll go through the steps required.

[ Unfortunately for you I'm running up-to-date kernels that already have the logical names, but I'll try to fake the situation you will be seeing. ]

Every UART (and tty of any kind) has an entry in /sys/class/tty/ - ..........

It is as you said, at the steps where you execute $ grep -a . /sys/firmware/devicetree/base/aliases/uart* I get different result from my machine:

Code: Select all

-r--r--r-- 1 root root 21 Oct  4 02:31 /sys/firmware/devicetree/base/aliases/uart0
-r--r--r-- 1 root root 21 Oct  4 02:42 /sys/firmware/devicetree/base/aliases/uart1
Due to the uart number is different so I can't relate it back to uart4 or uart5. Which leave us on the hexadecimal method. I just need to figure out how to calculate those values using bash instead of C...

PhilE
Raspberry Pi Engineer & Forum Moderator
Raspberry Pi Engineer & Forum Moderator
Posts: 5560
Joined: Mon Sep 29, 2014 1:07 pm
Location: Cambridge

Re: Possible to Assign Static Device Name to UART?

Wed Oct 04, 2023 6:03 am

Doesn't the bash code I've given you, using a case statement, work?

rasp14
Posts: 182
Joined: Sun Jun 22, 2014 2:49 pm

Re: Possible to Assign Static Device Name to UART?

Wed Oct 04, 2023 6:38 am

PhilE wrote:
Wed Oct 04, 2023 6:03 am
Doesn't the bash code I've given you, using a case statement, work?
It does work. I just wondering if there is a code that can directly calculate the number and I can use one line code like below:

Code: Select all

echo "$SERIAL_DATA" > /dev/ttyAMA$(insert formula here)
By the way, why the select case doesn't include uart1? I tried to turn uart1 on in config.txt but somehow it didn't show up after reboot. Here is what I get if I turn on uart1 to uart5 in dtoverlay. Seems like uart1 is missing.

Code: Select all

$ readlink /sys/class/tty/ttyAMA*/device/of_node
../../../../firmware/devicetree/base/soc/serial@7e201000
../../../../firmware/devicetree/base/soc/serial@7e201400
../../../../firmware/devicetree/base/soc/serial@7e201600
../../../../firmware/devicetree/base/soc/serial@7e201800
../../../../firmware/devicetree/base/soc/serial@7e201a00
Is this a bug in older kernel?

PhilE
Raspberry Pi Engineer & Forum Moderator
Raspberry Pi Engineer & Forum Moderator
Posts: 5560
Joined: Mon Sep 29, 2014 1:07 pm
Location: Cambridge

Re: Possible to Assign Static Device Name to UART?

Wed Oct 04, 2023 7:38 am

My suggestion would be to put the name of the UART device into a variable which is initialised once and used often. That way it doesn't matter if it takes a few lines of code to do it.
Is this a bug in older kernel?
It's not a bug - UART1 is a different type of UART (an 8250 clone) and appears as /dev/ttyS0.

Return to “Device Tree”