cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
Anonymous
Not applicable
4,720 Views

3 AXI UART (16550 style) cores in PL

Jump to solution

Hello everyone,

 

I've spent a week trying to get this to work and I'm out of ideas. I'm working on a project that requires 5 UART controller. I've enabled UART0 in PS and it's working. Now I have instantiated 3 AXI UART (16550 style) xilinx cores and connected them in XPS on the axi4lite bus. These are the generated addresses:

 

addresses.png

 

I then connected the interrupts to the GIC: 

Screenshot from 2014-07-21 17:47:42.png

 

The three pairs of RX & TX pins are connected to a PMOD.

 

I have attached the full dts file, in case I missed some other configs for the interrupt controller, but here are the relevant entries:

 

	serial@e0000000 {
    		clock-names = "ref_clk", "aper_clk";
		clocks = <0x3 0x17 0x3 0x28>;
		compatible = "xlnx,ps7-uart-1.00.a", "xlnx,xuartps";
		current-speed = <0x1c200>;
		interrupt-parent = <0x2>;
		interrupts = <0x0 0x1B 0x4>;
		reg = <0xe0000000 0x1000>;
		xlnx,has-modem = <0x0>;
    	};

	serial@e0001000 {
		clock-names = "ref_clk", "aper_clk";
		clocks = <0x3 0x18 0x3 0x29>;
		compatible = "xlnx,ps7-uart-1.00.a", "xlnx,xuartps";
		current-speed = <0x1c200>;
		interrupt-parent = <0x2>;
		interrupts = <0x0 0x32 0x4>;
		reg = <0xe0001000 0x1000>;
		xlnx,has-modem = <0x0>;
	};
		
	axi_uart0: serial@42A00000 {
    	    current-speed = <115200>;
            clock-frequency = <100000000>;
            compatible="ns16550a";
            interrupt-parent = <0x2>;
            interrupts = < 0x0 0x39 0x4>;
            reg = < 0x42A00000 0x10000 >;
            reg-offset = <0x1000>;
            reg-shift = <2>;
            xlnx,family = "zynq";
            xlnx,has-external-rclk = <0x0>;
            xlnx,has-external-xin = <0x0>;
            xlnx,is-a-16550 = <0x1>;
            xlnx,s-axi-aclk-freq-hz = <0x5F5E100>;
            xlnx,use-modem-ports = <0x0>;
            xlnx,use-user-ports = <0x0>;
            xlnx,instance = "axi_uart16550_0";
        };
        
        axi_uart1: serial@42A20000 {
            current-speed = <115200>;
            clock-frequency = <100000000>;
            compatible = "ns16550a";
            interrupt-parent = <0x2>;
            interrupts = < 0x0 0x38 0x4>;
            reg = < 0x42A20000 0x10000 >;
            reg-offset = <0x1000>;
            reg-shift = <2>;
            xlnx,family = "zynq";
            xlnx,has-external-rclk = <0x0>;
            xlnx,has-external-xin = <0x0>;
            xlnx,is-a-16550 = <0x1>;
            xlnx,s-axi-aclk-freq-hz = <0x5F5E100>;
            xlnx,use-modem-ports = <0x0>;
            xlnx,use-user-ports = <0x0>;
            xlnx,instance = "axi_uart16550_1";
        };

        axi_uart2: serial@42A40000 {
            current-speed = <115200>;
            clock-frequency = <100000000>;
            compatible = "ns16550a";
            interrupt-parent = <0x2>;
            interrupts = < 0x0 0x37 0x4>;
            reg = < 0x42A40000 0x10000 >;
            reg-offset = <0x1000>;
            reg-shift = <2>;
            xlnx,family = "zynq";
            xlnx,has-external-rclk = <0x0>;
            xlnx,has-external-xin = <0x0>;
            xlnx,is-a-16550 = <0x1>;
            xlnx,s-axi-aclk-freq-hz = <0x5F5E100>;
            xlnx,use-modem-ports = <0x0>;
            xlnx,use-user-ports = <0x0>;
            xlnx,instance = "axi_uart16550_2";
        };

 

Now the fun part: From the 3 cores, the second one is working fine! The other two appear in the boot sequence and in the /dev/ directory, but no interrupts are being generated and no traffic gets through.

 

I'm working with a zedboard and running:

Linux localhost.localdomain 3.12.0-xillinux-1.3-xilinx-dirty #11 SMP PREEMPT Mon Jul 21 17:14:34 EEST 2014 armv7l armv7l armv7l GNU/Linux

 

Any help is greatly appreciated!

 

0 Kudos
Reply
1 Solution

Accepted Solutions
Anonymous
Not applicable
6,510 Views

Ok, so the problem was that the interrupt wasn't matched with the correct core instance: axi_uart_16550_0 has base address 0x42A40000 and interrupt 89 and  axi_uart_16550_2 has address 0x42A00000 and interrupt 87. So the mistake was in the device tree source where it should be like this:

 

axi_uart0: serial@42A40000 {
current-speed = <115200>;
clock-frequency = <100000000>;
compatible="ns16550a";
interrupt-parent = <0x2>;
interrupts = < 0x0 0x39 0x4>;
reg = < 0x42A40000 0x10000 >;
reg-offset = <0x1000>;
reg-shift = <2>;
xlnx,family = "zynq";
xlnx,has-external-rclk = <0x0>;
xlnx,has-external-xin = <0x0>;
xlnx,is-a-16550 = <0x1>;
xlnx,s-axi-aclk-freq-hz = <0x5F5E100>;
xlnx,use-modem-ports = <0x0>;
xlnx,use-user-ports = <0x0>;
xlnx,instance = "axi_uart16550_0";
};

axi_uart1: serial@42A20000 {
current-speed = <115200>;
clock-frequency = <100000000>;
compatible = "ns16550a";
interrupt-parent = <0x2>;
interrupts = < 0x0 0x38 0x4>;
reg = < 0x42A20000 0x10000 >;
reg-offset = <0x1000>;
reg-shift = <2>;
xlnx,family = "zynq";
xlnx,has-external-rclk = <0x0>;
xlnx,has-external-xin = <0x0>;
xlnx,is-a-16550 = <0x1>;
xlnx,s-axi-aclk-freq-hz = <0x5F5E100>;
xlnx,use-modem-ports = <0x0>;
xlnx,use-user-ports = <0x0>;
xlnx,instance = "axi_uart16550_1";
};

 

axi_uart2: serial@42A00000 {
current-speed = <115200>;
clock-frequency = <100000000>;
compatible = "ns16550a";
interrupt-parent = <0x2>;
interrupts = < 0x0 0x37 0x4>;
reg = < 0x42A00000 0x10000 >;
reg-offset = <0x1000>;
reg-shift = <2>;
xlnx,family = "zynq";
xlnx,has-external-rclk = <0x0>;
xlnx,has-external-xin = <0x0>;
xlnx,is-a-16550 = <0x1>;
xlnx,s-axi-aclk-freq-hz = <0x5F5E100>;
xlnx,use-modem-ports = <0x0>;
xlnx,use-user-ports = <0x0>;
xlnx,instance = "axi_uart16550_2";
};

 

View solution in original post

0 Kudos
Reply
3 Replies
Anonymous
Not applicable
4,717 Views

So this is what happens at boot:

root@localhost:~# dmesg |grep serial
[    0.547895] e0000000.serial: ttyPS1 at MMIO 0xe0000000 (irq = 59, base_baud = 3124999) is a xuartps
[    0.555287] e0001000.serial: ttyPS0 at MMIO 0xe0001000 (irq = 82, base_baud = 3124999) is a xuartps
[   12.178423] 42a00000.serial: ttyS2 at MMIO 0x42a01000 (irq = 89, base_baud = 6250000) is a 16550A
[   12.201021] 42a20000.serial: ttyS3 at MMIO 0x42a21000 (irq = 88, base_baud = 6250000) is a 16550A
[   12.240373] 42a40000.serial: ttyS4 at MMIO 0x42a41000 (irq = 87, base_baud = 6250000) is a 16550A

 

Notice that the three PL cores are ttyS2, ttyS3 and ttyS4, probably because ttyS0 and ttyS1 have failed to map properly for the first two devices (the PS ones). They appear /dev but they aren't working at all. It is annoying to have two bogus devices in /dev, but I can like with it. The problem is with ttyS2 and ttyS4 (ttyS3 is working fine).

0 Kudos
Reply
Anonymous
Not applicable
6,511 Views

Ok, so the problem was that the interrupt wasn't matched with the correct core instance: axi_uart_16550_0 has base address 0x42A40000 and interrupt 89 and  axi_uart_16550_2 has address 0x42A00000 and interrupt 87. So the mistake was in the device tree source where it should be like this:

 

axi_uart0: serial@42A40000 {
current-speed = <115200>;
clock-frequency = <100000000>;
compatible="ns16550a";
interrupt-parent = <0x2>;
interrupts = < 0x0 0x39 0x4>;
reg = < 0x42A40000 0x10000 >;
reg-offset = <0x1000>;
reg-shift = <2>;
xlnx,family = "zynq";
xlnx,has-external-rclk = <0x0>;
xlnx,has-external-xin = <0x0>;
xlnx,is-a-16550 = <0x1>;
xlnx,s-axi-aclk-freq-hz = <0x5F5E100>;
xlnx,use-modem-ports = <0x0>;
xlnx,use-user-ports = <0x0>;
xlnx,instance = "axi_uart16550_0";
};

axi_uart1: serial@42A20000 {
current-speed = <115200>;
clock-frequency = <100000000>;
compatible = "ns16550a";
interrupt-parent = <0x2>;
interrupts = < 0x0 0x38 0x4>;
reg = < 0x42A20000 0x10000 >;
reg-offset = <0x1000>;
reg-shift = <2>;
xlnx,family = "zynq";
xlnx,has-external-rclk = <0x0>;
xlnx,has-external-xin = <0x0>;
xlnx,is-a-16550 = <0x1>;
xlnx,s-axi-aclk-freq-hz = <0x5F5E100>;
xlnx,use-modem-ports = <0x0>;
xlnx,use-user-ports = <0x0>;
xlnx,instance = "axi_uart16550_1";
};

 

axi_uart2: serial@42A00000 {
current-speed = <115200>;
clock-frequency = <100000000>;
compatible = "ns16550a";
interrupt-parent = <0x2>;
interrupts = < 0x0 0x37 0x4>;
reg = < 0x42A00000 0x10000 >;
reg-offset = <0x1000>;
reg-shift = <2>;
xlnx,family = "zynq";
xlnx,has-external-rclk = <0x0>;
xlnx,has-external-xin = <0x0>;
xlnx,is-a-16550 = <0x1>;
xlnx,s-axi-aclk-freq-hz = <0x5F5E100>;
xlnx,use-modem-ports = <0x0>;
xlnx,use-user-ports = <0x0>;
xlnx,instance = "axi_uart16550_2";
};

 

View solution in original post

0 Kudos
Reply
Participant
Participant
2,700 Views
Registered: ‎11-09-2015
I'm trying to implement interrupt handlers for two 16550 serial ports and I'm struggling. How did you get interrupt 87 and 89 from the definition in the device tree?
0 Kudos
Reply