0xStubs

System Administration, Programming and Reconfigurable Computing

Stuck UART on the ZedBoard

Recently I grabbed my trusted old Avnet / Digilent ZedBoard to test how well the current Xilinx tools work with this now a decade old platform. However, I was facing a weird issue: The serial output by the Zynq PS was only received via USB on my computer when I was sending characters via UART from my computer to the PS as well. As soon as there was a pause in communication, any further serial output by the PS was silently dropped.

I noticed that I could make the UART work again just by touching the device file corresponding to the USB-to-UART chip (e.g., /dev/ttyACM0). It looked like the USB-to-UART bridge was just falling asleep until I poked it either by sending data from the USB side or by touching the device file. Turns out, this is exactly what was happening. There is a USB feature called autosuspend which is enabled by default on Arch Linux and puts USB devices to sleep after 1-2 seconds of inactivity.

The cure

A simple fix for this issue is to create a udev rule that disables autosuspend for the USB-to-UART bridge used on the ZedBoard. To do so, just create a file, e.g. called cypress-cdc-acm.rules, in /etc/udev/rules.d with the following contents:

ACTION=="add|change", SUBSYSTEM=="usb", ATTR{idVendor}=="04b4", ATTR{idProduct}=="0008", TEST=="power/control", ATTR{power/control}="on"

The reason

USB autosuspend should normally not interfere with the functionality of the device but here it is clearly breaking the serial communication between the computer and the Zynq on the ZedBoard. So what is the reason for that and can it be fixed?

USB autosuspend is only enabled by the Linux kernel if the device advertises to support the remote wake-up functionality which allows the device to trigger a wake-up if it wants to transmit data to the host. And indeed, the Cypress CDC ACM bridge used on the ZedBoard advertises this functionality. But it obviously does not work in this case.

Looking at the schematic of the ZedBoard shows that the part number of the used Cypress chip is CY7C64225-28PVXC. Looking at its data sheet reveals that the remote wake-up is only triggered when a dedicated WAKE pin of the chip is asserted. On the ZedBoard this pin is tied to ground. The data sheet explicitly states that the pin is active high, so when it is tied to ground no wake-ups will ever be generated. Interestingly, the pin is marked as active low in the ZedBoard schematic, which might explain why we ended up with this issue…

So, the Cypress chip behaves like documented which means that no general solution can be implemented in the kernel or in udev. The problem is specific to the ZedBoard and to avoid it one must disable USB autosuspend for this device as shown above.

Debugging this was supported by the maintainer of the cdc-acm driver in Linux.

One Response to Stuck UART on the ZedBoard

  1. steve says:

    You are great for finding this. Cheers.

Leave a Reply

Your email address will not be published. Required fields are marked *

Captcha loading...