cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
nniles
Visitor
Visitor
4,419 Views
Registered: ‎10-28-2017

Zynq PS CAN bus on Linux

Jump to solution

I'm having an issue setting up the Zynq (7020 on a MicroZed board) PS CAN bus where no matter what I set in Vivado for the CAN clock speed, the Linux driver always sees it as 8 MHz (1 GHz IO PLL, first divided to 40 MHz, then divided to 8 MHz, according to /sys/kernel/debug/clk/clk_summary).

 

The bus I need to interact with operates at 1 MHz, so 8 MHz should, in theory, be okay, but I get a lot of (though far from 100%) bus errors, mostly CRC, with only the MicroZed and a Vector CANcaseXL on the bus.  The errors occur only when I use CANalyzer to send messages via the CANcaseXL in rapid succession.  Single messages in either direction aren't generating errors.  I haven't eliminated all possibilities for electrical issues, but...

 

My question here is, "Why isn't the xilinx_can Linux driver seeing the clock settings from Vivado?"  What could cause this disconnect?  I have tried setting it to 100 MHz, 50 MHz, 40 MHz, and 20 MHz, and the driver always reports 8 MHz.

 

My Linux build setup is Yocto (pyro) with enough customizations on meta-xilinx to get the device tree and platform-init files into the MicroZed-/core-image-minimal -based build.  I have verified that these are being used in the build, and that the platform-init files have the intended settings for the CAN clock divisors.  My device tree matches (for can_0, at least) the suggestions on the Xilinx Wiki page.  As mentioned above, it is almost working, but I am unable to experiment with different timings, beyond changing the sample point with iproute2 (not many choices without being able to change the CAN clock).

 

Any help would be appreciated.  I can provide configurations and screen shots upon request.

Tags (3)
0 Kudos
Reply
1 Solution

Accepted Solutions
nniles
Visitor
Visitor
6,025 Views
Registered: ‎10-28-2017

Well, it turns out that I had a Yocto recipe extension file (.bbappend) misnamed.

 

I needed to set a Yocto environment variable FORCE_PLATFORM_INIT="1" to get the ps7_init_gpl.[c/h] moved into the u-boot sources - which I thought I had done.  Unfortunately, I put it in a filed called "u-boot-xlnx-2017.1.bbappend", but it should have been in a file called "u-boot_%.bbappend", since the "MACHINE" I'm building for sets virtual/bootloader="u-boot", as opposed to u-boot-xlnx.

 

Thanks again for pointing me in the right direction to diagnose my problem!

View solution in original post

0 Kudos
Reply
8 Replies
hpoetzl
Voyager
Voyager
4,410 Views
Registered: ‎06-24-2013

Hey @nniles,

 

Device Tree and Kernel Version/Config would help.

 

Best,

Herbert

-------------- Yes, I do this for fun!
0 Kudos
Reply
nniles
Visitor
Visitor
4,363 Views
Registered: ‎10-28-2017

Thanks, Herbert.

 

I am using kernel 4.9 (linux-xilinx_2017.1) with the following config fragment (i.e., overrides from the default).

#
# Processor Features
#
# CONFIG_DEBUG_RODATA is not set
# CONFIG_DEBUG_ALIGN_RODATA is not set
#
# Kernel Features
#
CONFIG_PREEMPT_RT_FULL=y
# CONFIG_HZ_100 is not set
CONFIG_HZ_1000=y
CONFIG_HZ=1000
#
# Networking support
#
CONFIG_NET_DEVLINK=y
# CONFIG_WIRELESS is not set
#
# Networking options
#
# CONFIG_IP_MULTICAST is not set
# CONFIG_INET_TUNNEL is not set
# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
# CONFIG_INET_XFRM_MODE_TUNNEL is not set
# CONFIG_INET_XFRM_MODE_BEET is not set
# CONFIG_INET_DIAG is not set
# CONFIG_INET_TCP_DIAG is not set
# CONFIG_INET6_XFRM_MODE_TRANSPORT is not set
# CONFIG_INET6_XFRM_MODE_TUNNEL is not set
# CONFIG_INET6_XFRM_MODE_BEET is not set
CONFIG_NETWORK_PHY_TIMESTAMPING=y
CONFIG_NETLINK_DIAG=y
#
# Network testing
#
CONFIG_CAN_RAW=y
# CONFIG_CAN_BCM is not set
# CONFIG_CAN_GW is not set
#
# CAN Device Drivers
#
CONFIG_CAN_VCAN=m
CONFIG_CAN_CALC_BITTIMING=y
CONFIG_CAN_DEBUG_DEVICES=y
#
# Input Device Drivers
#
CONFIG_KEYBOARD_GPIO=y
CONFIG_KEYBOARD_GPIO_POLLED=y
#
# SPI Protocol Masters
#
CONFIG_SPI_SPIDEV=y
#
# Kernel hacking
#
#
# Compile-time checks and compiler options
#
# CONFIG_DEBUG_KERNEL is not set
#
# Debug Lockups and Hangs
#
# CONFIG_SCHED_DEBUG is not set
# CONFIG_DEBUG_PREEMPT is not set
#
# Lock Debugging (spinlocks, mutexes, etc...)
#
# CONFIG_DEBUG_BUGVERBOSE is not set

 

The device tree is nearly straight from the Xilinx device-tree tool, with the majority coming from the basic zynq-7000.dtsi, which has the following for can0:

...
/ {
...
	amba: amba {
...
		can0: can@e0008000 {
			compatible = "xlnx,zynq-can-1.0";
			status = "disabled";
			clocks = <&clkc 19>, <&clkc 36>;
			clock-names = "can_clk", "pclk";
			reg = <0xe0008000 0x1000>;
			interrupts = <0 28 4>;
			interrupt-parent = <&intc>;
			tx-fifo-depth = <0x40>;
			rx-fifo-depth = <0x40>;
		};
...
	};
...
};

 

The only addition related to CAN, in a file called "pcw.dtsi" generated by the device-tree tool, is:

 

&can0 {
	status = "okay";
};

Note that I am using the generated device-tree files directly, though I had to add a bit (found somewhere?) to get ethernet working (note that this is my "top level" device-tree source):

 

/include/ "system-top.dts"
/include/ "local-gpios.dtsi"
&gem0 {
	/* these are somehow missing from the Xilinx tool-generated device-tree files */
	phy-handle = <&ethernet_phy>;

	ethernet_phy: ethernet-phy@0 {
		reg = <0>;
	};
	/* we will let u-boot pick a random MAC address */
};
0 Kudos
Reply
hpoetzl
Voyager
Voyager
4,353 Views
Registered: ‎06-24-2013

Hey @nniles,

 

Okay, so changing the clock frequency in the PS configuration of Vivado will only affect the register settings when you create a new FSBL to apply them (or apply the PLL/divider register settings yourself). This also assumes that the kernel does not change them back (for whatever reason).

 

On the other hand, the PS CAN bus driver supports bitrate settings, so changing the CAN bus to 1MHz should ony require you to use 'canconfig ... bitrate 1000000' to change the bitrate based on whatever clock the peripherial is currently using.

 

Hope this helps,

Herbert

-------------- Yes, I do this for fun!
0 Kudos
Reply
nniles
Visitor
Visitor
4,342 Views
Registered: ‎10-28-2017

Thanks again for your response, Herbert.

 

1. I'm using Yocto (meta-xilinx) to build the bootloader and O/S.  I think, based on internet searches, it is using U-boot SPL rather than FSBL.  There is a package being built (and included, as far as I can tell) called platform-init that uses the ps7_init_gpl.[c/h] sources that are generated by Vivado/SDK.  I have confirmed that ps7_init_gpl.c contains the register settings corresponding to the Zynq configuration I specified in Vivado (e.g., divisor0=10 and divisor1=5 should yield the 20 MHz CAN clock from the 1 GHz I/O PLL).

    // .. CLKACT0 = 0x1
    // .. ==> 0XF800015C[0:0] = 0x00000001U
    // ..     ==> MASK : 0x00000001U    VAL : 0x00000001U
    // .. CLKACT1 = 0x0
    // .. ==> 0XF800015C[1:1] = 0x00000000U
    // ..     ==> MASK : 0x00000002U    VAL : 0x00000000U
    // .. SRCSEL = 0x0
    // .. ==> 0XF800015C[5:4] = 0x00000000U
    // ..     ==> MASK : 0x00000030U    VAL : 0x00000000U
    // .. DIVISOR0 = 0xa
    // .. ==> 0XF800015C[13:8] = 0x0000000AU
    // ..     ==> MASK : 0x00003F00U    VAL : 0x00000A00U
    // .. DIVISOR1 = 0x5
    // .. ==> 0XF800015C[25:20] = 0x00000005U
    // ..     ==> MASK : 0x03F00000U    VAL : 0x00500000U
    // .. 
    EMIT_MASKWRITE(0XF800015C, 0x03F03F33U ,0x00500A01U),
    // .. CAN0_MUX = 0x0
    // .. ==> 0XF8000160[5:0] = 0x00000000U
    // ..     ==> MASK : 0x0000003FU    VAL : 0x00000000U
    // .. CAN0_REF_SEL = 0x0
    // .. ==> 0XF8000160[6:6] = 0x00000000U
    // ..     ==> MASK : 0x00000040U    VAL : 0x00000000U
    // .. CAN1_MUX = 0x0
    // .. ==> 0XF8000160[21:16] = 0x00000000U
    // ..     ==> MASK : 0x003F0000U    VAL : 0x00000000U
    // .. CAN1_REF_SEL = 0x0
    // .. ==> 0XF8000160[22:22] = 0x00000000U
    // ..     ==> MASK : 0x00400000U    VAL : 0x00000000U
    // .. 

I am cleaning and rebuilding the pertinent Yocto packages between configuration changes, and have even rebuilt from scratch to no effect.

 

2. I assume that you are referring to the canconfig utility from the Xilinx CAN Wiki, which is only provided in binary format?  I have not been able to get that to run.  After I copy all of those files from the archive onto the system, when I attempt to run canconfig, bash says something to the effect of it can't find canconfig, even if the cwd is the directory with canconfig and I call it with ./canconfig.

 

One of the reasons I'm set on finding the right way to pull the device configuration in from Vivado into Yocto (as opposed to pursuing the canconfig route), is that I have many other devices I need to add to my system, and this issue suggests that I'm missing something crucial, and that I will have the same problem on the next device if I kick the can down the road by taking a workaround now.

 

Thanks again!

0 Kudos
Reply
hpoetzl
Voyager
Voyager
4,332 Views
Registered: ‎06-24-2013

Hey @nniles,

 

Thanks again for your response

You're welcome!

 

I have confirmed that ps7_init_gpl.c ...

Okay, that is an important fact, which means that the register settings are at least present.

 

The next step is to confirm that they are applied as expected ...

I.e. use the u-boot memory access commands to check if they have the proper values before the kernel is booted and use devmem to inspect them after the kernel boot ...

 

bash says something to the effect of it can't find canconfig ...

This is most likely the result of a missing library, check with the 'ldd' command (or if that is missing directly with 'LD_TRACE_LOADED_OBJECTS=1 /path/to/canconfig'

 

I will have the same problem on the next device if I kick the can down the road by taking a workaround now

Note that adjusting the bitrate is not a workaround but an alternate aspect of your configuration.

Most of the hardened peripherials (as well as many soft peripherials) have a clock and a bitrate generator. The former provides the base while the latter controls the data rate, adding stuff like oversampling etc. The short version here is: you usually do not want a 1MHz clock for a 1Mbit datarate because that will disable any oversampling and filtering.

 

Hope this clarifies,

Herbert

-------------- Yes, I do this for fun!
nniles
Visitor
Visitor
4,312 Views
Registered: ‎10-28-2017

Awesome(?), that clears up part of the problem, thanks.

Zynq> md f800015c
f800015c: 00501903 00000000 00000f03 00000501    ..P.............

Should have been: 00500a01

 

Now I just have to figure out how to get the ps7_init code to be included/work.

0 Kudos
Reply
hpoetzl
Voyager
Voyager
4,301 Views
Registered: ‎06-24-2013

You're welcome!

 

Let me know how it goes ...

 

Best,

Herbert

-------------- Yes, I do this for fun!
nniles
Visitor
Visitor
6,026 Views
Registered: ‎10-28-2017

Well, it turns out that I had a Yocto recipe extension file (.bbappend) misnamed.

 

I needed to set a Yocto environment variable FORCE_PLATFORM_INIT="1" to get the ps7_init_gpl.[c/h] moved into the u-boot sources - which I thought I had done.  Unfortunately, I put it in a filed called "u-boot-xlnx-2017.1.bbappend", but it should have been in a file called "u-boot_%.bbappend", since the "MACHINE" I'm building for sets virtual/bootloader="u-boot", as opposed to u-boot-xlnx.

 

Thanks again for pointing me in the right direction to diagnose my problem!

View solution in original post

0 Kudos
Reply