cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
Advisor
Advisor
788 Views
Registered: ‎10-10-2014

how to match ttyUL* devices with the corresponding UartLite instances in the vivado design

Jump to solution

I have a Zynq design with 5 UartLite devices in the PL. After booting linux, these appear as :

ls /dev | grep ttyUL
ttyUL0
ttyUL2
ttyUL3
ttyUL4
ttyUL5

now how can I figure out which ttyULx devices corresponds to each uartlite in my BD?

 Screenshot 2020-04-23 at 17.54.41.pngScreenshot 2020-04-23 at 17.54.56.png

I know these uartlites can be found in the device tree, i.e. the first 2 :

		mcu_ctrl_axi_uartlite_0: serial@a0013000 {
			clock-names = "s_axi_aclk";
			clocks = <&clk 71>;
			compatible = "xlnx,axi-uartlite-2.0", "xlnx,xps-uartlite-1.00.a";
			current-speed = <115200>;
			device_type = "serial";
			interrupt-names = "interrupt";
			interrupt-parent = <&gic>;
			interrupts = <0 89 1>;
			port-number = <0>;
			reg = <0x0 0xa0013000 0x0 0x1000>;
			xlnx,baudrate = <0x1c200>;
			xlnx,data-bits = <0x8>;
			xlnx,odd-parity = <0x0>;
			xlnx,s-axi-aclk-freq-hz-d = "115.373085";
			xlnx,use-parity = <0x0>;
		};
		mcu_ctrl_axi_uartlite_1: serial@a0014000 {
			clock-names = "s_axi_aclk";
			clocks = <&clk 71>;
			compatible = "xlnx,axi-uartlite-2.0", "xlnx,xps-uartlite-1.00.a";
			current-speed = <921600>;
			device_type = "serial";
			interrupt-names = "interrupt";
			interrupt-parent = <&gic>;
			interrupts = <0 90 1>;
			port-number = <2>;
			reg = <0x0 0xa0014000 0x0 0x1000>;
			xlnx,baudrate = <0xe1000>;
			xlnx,data-bits = <0x8>;
			xlnx,odd-parity = <0x0>;
			xlnx,s-axi-aclk-freq-hz-d = "115.373085";
			xlnx,use-parity = <0x0>;
		};

how can I know from user space, without hard-coding the addresses of the 5 uarts, which ttyULx corresponds i.e. to instance 'mcu_ctrl_axi_uartlite_0' of my block design? 

I also think linux might enumerate these in different order between reboots, is that correct?

** kudo if the answer was helpful. Accept as solution if your question is answered **
0 Kudos
Reply
1 Solution

Accepted Solutions
Scholar
Scholar
729 Views
Registered: ‎10-21-2015

Hi

In ttyULx, x is determined by port-number property in devicetree

Refer to https://github.com/Xilinx/linux-xlnx/blob/master/drivers/tty/serial/uartlite.c#L866

You can redefine port-number for each node in system-user.dtsi

&mcu_ctrl_axi_uartlite_1 {
      port-number = <1>;
};

View solution in original post

6 Replies
Scholar
Scholar
748 Views
Registered: ‎05-28-2013

The physical address of each UART is baked into the PL (eg. set by the PL designer), you can see the values in Address Editor as per your screenshot. For example mcu_ctrl_axi_uartlite_0 is at 0xa0013000.

The same address appears in the device tree, specifically in the line:

reg = <0x0 0xa0013000 0x0 0x1000>;

The kernel will process the device tree, and will assign a ttyUL* essentially sequentially, following the order of the device tree. These will generally stay fixed across reboots, though if you change kernel configuration (adding/removing device drivers) or device tree, the ordering could change as a result.

If you wish to "lock in" specific ttyUL numbers, it can be done by adding an "aliases" section, normally at the top of the device tree:

aliases {
        serial0 = &mcu_ctrl_axi_uartlite_0;
        serial1 = &mcu_ctrl_axi_uartlite_1;
        ...etc...
};
Scholar
Scholar
730 Views
Registered: ‎10-21-2015

Hi

In ttyULx, x is determined by port-number property in devicetree

Refer to https://github.com/Xilinx/linux-xlnx/blob/master/drivers/tty/serial/uartlite.c#L866

You can redefine port-number for each node in system-user.dtsi

&mcu_ctrl_axi_uartlite_1 {
      port-number = <1>;
};

View solution in original post

Advisor
Advisor
686 Views
Registered: ‎10-10-2014

thanks @hokim  and @rfs613 , that's very usefull info ...

however @rfs613 , could it be that this phrase 'The kernel will process the device tree, and will assign a ttyUL* essentially sequentially, following the order of the device tree.' is not 100% correct? as @hokim says, it's determined by the entry 'port-number = <1>;'

I can see this corresponds between my dts file and 'ls /dev | grep ttyUL'  :

ls /dev | grep ttyUL
ttyUL0
ttyUL2
ttyUL3
ttyUL4
ttyUL5

so now I also see why there is no ttyUL1, as the <port-number> entries for my 5 uart lites are 0, 2, 3, 4, 5 in the device tree.

Now I'm wondering exactly why Vivado 'skipped' the number '1' when generating the info in the .hdf which is translated by the hsi tool into a dts node ... is there any way this port-number can be set in the IP in Vivado before building the bitstream and .hdf file? Maybe in the 'block properties'? (but I don't see where ...

Screenshot 2020-04-24 at 11.10.38.png

I know I can override this in a 'user dtsi' later on, but it would be more interesting if it was already fixed in the .hdf file comming out of Vivado ... (maybe I deleted one UART lite during the building of the block design, and Vivado took the next index ...   

** kudo if the answer was helpful. Accept as solution if your question is answered **
0 Kudos
Reply
Scholar
Scholar
670 Views
Registered: ‎05-28-2013

however @rfs613 , could it be that this phrase 'The kernel will process the device tree, and will assign a ttyUL* essentially sequentially, following the order of the device tree.' is not 100% correct? as @hokim says, it's determined by the entry 'port-number = <1>;'

It would seem that the uartlite driver doesn't follow the standard convention used in most other kernel drivers (ttyS*, i2c, spi, etc...). But at least it has some mechanism to specify the numbering.

As for where Vivado is coming up with those numbers, regrettably I also don't know...

Advisor
Advisor
602 Views
Registered: ‎10-10-2014

thanks @rfs613, I'll rebuild my linux with the aliases in the device tree. 

Last question if I may : so if I add for example this alias :

aliases {
        serial0 = &mcu_ctrl_axi_uartlite_0;
};

that alias then appears as an entry in the /dev somewhere? So if I want to echo to the ttyUL0, I can just use :

echo "test" > /dev/serial0
** kudo if the answer was helpful. Accept as solution if your question is answered **
0 Kudos
Reply
Scholar
Scholar
586 Views
Registered: ‎05-28-2013

Actually, you will need to use port-number as per @hokim. The uartlite driver does not appear to support aliases.

Both methods are similar, in that they change the instance number that follows "/dev/ttyUL". The name will not change to "serial0".

The uartlite driver's probe function includes:

 

	prop = of_get_property(pdev->dev.of_node, "port-number", NULL);
	if (prop)
		id = be32_to_cpup(prop);

In contrast, the method using aliases can be found in the 8250 driver:

	/* Check for a fixed line number */
	ret = of_alias_get_id(np, "serial");
	if (ret >= 0)
		port->line = ret;

Searching for all calls to of_alias_get_id() shows that it is used in a large number serial drivers, as well as in some ethernet, i2c, gpio, and spi drivers.