cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
kabba
Observer
Observer
4,558 Views
Registered: ‎12-02-2014

Zynq Ultrascale+ MPSoC USB CDC Device, help & information.

Hi All

 

I am fairly new to the software side of things, I am a VHDL Firmware & electronic designer who is trying to get back up to speed with software to be better equipped to complete designs on the Zynq US+ architecture.

 

I have been tasked with trying to configure the Zynq US+ USB Driver (PS Side) to act as a CDC device to a Windows PC for standalone and usable with FreeRTOS. I want to use this as main comms to my system as the UARTs 0 and 1 will be used for other comms. We want R5 processor to be the main comms handler.

 

I went through the basics of the USB protocol and have been looking at 

https://xilinx-wiki.atlassian.net/wiki/spaces/A/pages/18841624/Zynq-7000+AP+SoC+USB+CDC+Device+Class+Design+Example+Techtip

 

as an example in setting up such a device.

 

I see that our ZCU106 eval kit only instantiates the XUsbPsu Driver on the SDK with board file defaults. Am I right in assuming that this is the only driver I have access to because of the USB3.0 functionality added and that the XUsbPs driver is only for the Zynq7000 devices?

 

The Driver API Documentation usually located at:

<Install Dir>/SDK/2018.2/data/embeddedsw/XilinxProcessorIPLib/drivers/usbpsu_v1_4/doc/html/api/

I am finding very sparse in terms of explaining the functionionality and makes me feel like I am missing quite some beforehand knowledge of the Driver API.

 

I have found quite a few differences between the Z7000 tech tips example code and what I can find in the Xusbpsu driver code xusbpsu.h, xusbpsu_hw.h , ect.

 

In short my questions would be:

 

What are the differences between the xusbps and xusbpsu drivers? Is it worth while to try and port the example to be compatible with the xusbpsu driver, or are the differences too great?

 

Is there any documentation that I might be missing to help me understand how to implement the CDC class USB device via Xilinx Drivers on the SDK for standalone use? Maybe Docs that Describe the use of the API to setup the Descriptors and endpoints for different types of uses (such as CDC, HID, ect).

 

Apologies if I am going about this the wrong way, but any help and suggestions will be greatly appreciated. :)

 

Thank you in advance

Christo Steyn

 

 

Tags (1)
0 Kudos
20 Replies
aresis
Newbie
Newbie
4,423 Views
Registered: ‎06-14-2018

Hi All,

I have exactly the same wish: USB CDC device bare metal (or FreeRTOS) driver and example for ZynqMP.

There is USB CDC device driver for Linux on the net but nothing for bare metal or RTOS. At least I was not able to find any.

Does anybody know if there is one somewhere?

Were it possible that Xilinx adds CDC example in the next release of SDK? I think that would be greatly appreciated by many developers.

Thank you,

Igor Poberaj

 

0 Kudos
kabba
Observer
Observer
4,366 Views
Registered: ‎12-02-2014

Hi aresis

I have not had much luck asof yet to find a Zynq Ultrascale+ MPSoC USB3.0 example to use easily. I did find a standalone example for Zynq7000 here:

https://xilinx-wiki.atlassian.net/wiki/spaces/A/pages/18841624/Zynq-7000+AP+SoC+USB+CDC+Device+Class+Design+Example+Techtip

I am currently trying to work from the XUSBPSU driver's storage device example and modify it to what I see happening in the techtip's source code.

The issue is mostly that there is quite a difference between the two device's drivers. So I've gotten it to the point that windows at least sees that it is trying to be a Serialport but no functionality works thus far.

Hopefully this helps you in any way. I think we are stuck to such attempts until Xilinx does us a solid and adds a similar example for the Ultrascale+ Zynq devices.

Good luck!

0 Kudos
sabinoxilinx1
Observer
Observer
4,196 Views
Registered: ‎01-23-2019

Hi Kabba

do you have solved the problem? I'm developping the cdc communication driver for the Ultra96 Board on ArmR5. I have started to change the mass storage example and now Windows10 is able to see the CDC Device and configuring it as a ComPort16. I have setted this endpoint 

+++++++ Into the Main ++++++++++

/* Assign the data to usb driver */
Set_DrvData(UsbInstance.PrivateData, &storage_data);

EpConfigure(UsbInstance.PrivateData, 0, USB_EP_DIR_OUT, USB_EP_TYPE_CONTROL);
EpConfigure(UsbInstance.PrivateData, 0, USB_EP_DIR_IN, USB_EP_TYPE_CONTROL);

EpConfigure(UsbInstance.PrivateData, 1, USB_EP_DIR_OUT, USB_EP_TYPE_INTERRUPT);
EpConfigure(UsbInstance.PrivateData, 1, USB_EP_DIR_IN, USB_EP_TYPE_INTERRUPT);

EpConfigure(UsbInstance.PrivateData, 2, USB_EP_DIR_OUT, USB_EP_TYPE_BULK);
EpConfigure(UsbInstance.PrivateData, 2, USB_EP_DIR_IN, USB_EP_TYPE_BULK);

Status = ConfigureDevice(UsbInstance.PrivateData, &Buffer[0], MEMORY_SIZE);
if (XST_SUCCESS != Status) {
return XST_FAILURE;
}

/*
* set endpoint handlers
* BulkOutHandler - to be called when data is received
* BulkInHandler - to be called when data is sent
*/
SetEpHandler(UsbInstance.PrivateData, 0, USB_EP_DIR_OUT, EpCtrlHandler);
SetEpHandler(UsbInstance.PrivateData, 0, USB_EP_DIR_IN, EpCtrlHandler);

SetEpHandler(UsbInstance.PrivateData, 1, USB_EP_DIR_OUT, EpIntrInHandler);
SetEpHandler(UsbInstance.PrivateData, 1, USB_EP_DIR_IN, EpIntrInHandler);

SetEpHandler(UsbInstance.PrivateData, 2, USB_EP_DIR_OUT, BulkOutHandler);
SetEpHandler(UsbInstance.PrivateData, 2, USB_EP_DIR_IN, BulkInHandler);

 

+++++++ End Main ++++++++++

###### Endpoint function ####

void EpCtrlHandler(void *CallBackRef, u32 RequestedBytes, u32 BytesTxed)
{
xil_printf("EpCtrlHandler\r\n");

}
void EpIntrInHandler(void *CallBackRef, u32 RequestedBytes, u32 BytesTxed)
{
xil_printf("EpIntrInHandler\r\n");
}

###################

When I start the code the EpCtrlHandler is called 10 times ( is see the printed string) and if I try to connect with realterm it's going in error. ( the device is not functioning )

Did you find a solution?

Regards
Sab

0 Kudos
kabba
Observer
Observer
4,174 Views
Registered: ‎12-02-2014

Hi sabinoxilinx1

If you can get it recognised as a serial device and it gets a comport assigned I am then assuming that your descriptors are correctly setup.

If your terminal program hangs and crashes upon selecting the com port 16 I also had this problem. My problem was within the class request handling. The CDC device basicly requires you to handle three class requests. Namely:

- CDC Request Line coding (SetupData->bRequest = 0x21). 

Here the device sends 7 bytes communicating to the host it's baud rate, stop bits and so on. the Baud rate itself is irrelevant it just has to be handled upon connecting the terminal program when it sends the class requests. 
Mine was setup as 

u8 xusb_cdc_line_coding[7] = {0x00, 0xc2, 0x01, 0x00, 0x00, 0x00, 0x08};

and sent by

EpBufferSend(InstancePtr->PrivateData, 0, xusb_cdc_line_coding, 7);

This communicates a 115200 Baudrate, parity none, 1 stop bit and 8 data bits.

 

- CDC Request Set line coding (SetupData->bRequest = 0x20)

Here you have to receive the coding bytes from the PC with

EpBufferRecv(InstancePtr->PrivateData, 0, buffer, SetupData->wLength);

and you can copy into your byte array storing the coding with

memcpy(xusb_cdc_line_coding, buffer, 7);

So that it gets reported as changed if the Host asks again.

Also remember to send a zero length acknowledge packet to acknowledge that you received the new line coding data with

EpBufferSend(InstancePtr->PrivateData, 0, NULL, 0);

- CDC Request Set Carrier (SetupData->bRequest = 0x22)

Nothing needs to be handled here, just ensure to send a zero length packet again to acknowledge again.

 

I hope this helps! I was developing this for the Zynq US+ MPSoC device. But the core idea is the same. When you connect the terminal program the CDC driver will send these class requests and if it is not acknowledged and handled the terminal sits waiting, hence the non responsive state it goes in before crashing. I use it with both TeraTerm and Termite programs but not realterm.

 

Lastly and extra note is that when I got this working I struggledd to get the data received handler to call. This in the Zynq MPSoC device USB driver meant that I first had to at least call the EpRecBuffer function once for at least one byte before data would be received and the handler called. But this is specific to the device and it's own USB driver code that you are using. For example the Zynq7000 device had a EpPrime function that served this purpose apart from it's own Receive function.

 

Best of luck!

Good day

sabinoxilinx1
Observer
Observer
4,134 Views
Registered: ‎01-23-2019

Hi Kabba

thank you for your answer. I have worked on your suggestion and after fixing the configuration now I have a working connection.
I'm abble to connect/disconnect multiple time on the Com17 without problem. One strange thing is that the exchange of this commands 

- CDC Request Line coding (SetupData->bRequest = 0x21).      ( 2x befor the connection to the com17 and 28 after )
- CDC Request Set line coding (SetupData->bRequest = 0x20)  ( 1x before conn and 8x after )
- CDC Request Set Carrier (SetupData->bRequest = 0x22)         ( 2x before conn and 10x after )

are done several time, is it normal?

Now I'm trying to send/receive 1byte on the com17 without success.With the USB Monitoring tool ( see fig1) I have seen 3 open pipe and I think that the com port should work.(1 Endpoint Interrupt and 2 Endpoint IN+OUT). I have tested your last solution to start the communication but the only handler that I have triggered is the send Handler without seeing data on the serial terminal. I think that the above multiple request are not ok, but I'll continue to analize.

Thank you 

1.jpg
sabinoxilinx1
Observer
Observer
4,069 Views
Registered: ‎01-23-2019

Hi Kabba

Just started again to work with the Ultra96 and finally the communication is working :-) 
In attached there is the code with the CDC ACM configuration. 

It was not working because into the previouse configuration the address of the EndPoint OUT Bulk 2 was wrong. 

Here are two good sources to study

http://janaxelson.com/usb_virtual_com_port.htm
http://www.keil.com/pack/Doc/MW/USB/html/_c_d_c.htm

Ciao and thank you again

 

txRxOK.png
broermank
Observer
Observer
3,498 Views
Registered: ‎08-28-2018

Hello,

I am in the same boat as you, looking for bare-metal USB-CDC device class example code for the Ultrascale.  (similar to that provided by   https://xilinx-wiki.atlassian.net/wiki/spaces/A/pages/18841624/Zynq-7000+AP+SoC+USB+CDC+Device+Class+Design+Example+Techtip)

Has anyone solved this problem, or have code they can share?

 

Thanks,

Keith

0 Kudos
charschu
Participant
Participant
2,869 Views
Registered: ‎08-08-2019

Can you tell me the What is the vivado version to use?

 

 

thanks!

0 Kudos
broermank
Observer
Observer
2,849 Views
Registered: ‎08-28-2018

SDK 2019.1 is needed for USB operation on Ultrascale

0 Kudos
charschu
Participant
Participant
2,815 Views
Registered: ‎08-08-2019

thank you very much 
I have a problem here,

The Pc can receive the data sent by the zcu102 board card,
but the data sent to the board card fails,
the debugging information show bulkout endpoint event.
Type =<0x3> not ready, endpoint event-state =0x0,
so I want to confirm a few points:

1. Can you provide the com driver of your PC

2. What is the serial port tool of your PC

3. What version of the usb grab tool do you use

I am very willing to learn from you

0 Kudos
abelo
Visitor
Visitor
2,778 Views
Registered: ‎04-08-2020

Hi sabinoxilinx1!

First, thanks for the great example! I just recently started to test things out with the Zynq Ultrascale+ MPSOC and ended up on this thread in the need of an USB CDC driver for baremetal.

Your example worked almost right off the bat. I got the connection up and my PC registered a COM port for the device. I can successfully connect/disconnect to the board over a serial connection using the registered COM port.

However, when I try sending even one byte character to the device, the terminal hangs. I can see from Vitis Terminal that the callback functions BulkOutHandler and BulkInHandler don't get called at all.

As I said, I'm using the example you provided as is and it's running on Zynq Ultrascale+ MPSOC.

Could you (or anyone) throw in a guess or anything as to what might still be wrong with this?

Thank you!

0 Kudos
abelo
Visitor
Visitor
2,603 Views
Registered: ‎04-08-2020

This issue is now solved for me and the USB CDC baremetal driver is working correctly. So here's a step by step of how I got it working using sabinoxilinx1's example on Zynq Ultrascale+ MPSOC:

  1. Unzipped sabinoxilinx1's example "my_cdc_acm_xusb_intr_example.7z"
  2. Started a new project in Vitis for Ultrascale+ Platform (had my own .xsa file)
  3. Imported the contents of the "src" folder into my project.
  4. Built and ran the project on the target. Worked right off the bat.
  5. Opened a terminal connection on Vitis on board side using baud rate 115200 and default settings.
  6. Connected the board to PC using the USB port labeled on the board as "USB 3 DEVICE"

At this point the PC succesfully set up all the descriptors and opened a COM port for the device and I could connect to the board. I used RealTerm for this. When I sent data however, the terminal froze and I could see from Wireshark that the packet went off but nothing happened after that.

To fix this I had to change the Bulk IN and OUT enpoint address as sabinoxilinx1 mentioned in his comment. So:

  1. I navigated to file xusb_ch9_storage.c, and around line index 123.
  2. In the data structure "config3", under comment *Bulk In Endpoint Config* I changed the field USB_EP1_IN (0x81) to USB_EP2_IN (0x82)
  3. Under comment *Bulk Out Endpoint Config* I changed the field USB_EP1_OUT (0x01) to USB_EP2_OUT (0x02).
  4. Build and ran on target.

And that's it. 

So basically sabinoxilinx1's example was working as intended, it was just missing the address fix that he mentioned.

ALSO:

I think it's worth mentioning that the same example code worked both on the ARM R5 as well as ARM A53 cores without any change in the code.

Thanks again sabinoxilinx1 and kabba for the work.

 

Tags (1)
sabinoxilinx1
Observer
Observer
2,580 Views
Registered: ‎01-23-2019

Hi abelo

I'm glad that my code helped you. Great job for the description how to start from scratch and also for the fix of the endpoint.


Ciao

0 Kudos
abelo
Visitor
Visitor
2,544 Views
Registered: ‎04-08-2020

Hi all,

Just wanted to share another issue I faced when trying to make a command interface over the serial connection.

The bulk endpoint callback functions always reported 0 bytes as the length of the received data. This was obviously a problem when trying to parse the incoming messages.

Luckily someone smarter had already figured this out on this thread: https://forums.xilinx.com/t5/Xilinx-Evaluation-Boards/ZynqMP-USB-Bare-Metal-Driver-Sharing-a-solution-to-the-problem/td-p/998056

The library function that calls the bulk endpoint callback function has a small issue. It uses a 64 bytes aligned struct "XUsbPsu_Trb" to store the amount bytes received. This alignment however fails for some reason.

To ensure that the alignment happens, we add a padding of 12 bytes into the struct in the header file "xusbpsu.h".

So again to put it simply:

  1. Find your way to "xusbpsu.h".
  2. Locate struct "XUsbPsu_Trb"
  3. Add a new data field  "u32 Padding[12];" in the struct.

With this "simple" fix, the callback function now reports the received byte count correctly.

 

You can find a more detailed answer by the original poster through the link provided above.

Thanks.

eorojas
Observer
Observer
2,414 Views
Registered: ‎01-29-2020

4-24-2020 and the questions are still the same.  One wonders why Xilinx doesn't do a better job of documenting their code and make more robust examples.

0 Kudos
eorojas
Observer
Observer
2,376 Views
Registered: ‎01-29-2020

Working on the same issue.  I'm grateful that you all shared your wisdom.


In point 3.
Add a new data field  "u32 Padding[12];" in the struct.

you say you added 12 bytes, but this Padding is 12 * 4 or 48 bytes.  I'll do it like this, but if you are able to comment, which is correct?
thanks

eorojas
Observer
Observer
2,305 Views
Registered: ‎01-29-2020

0 Kudos
abelo
Visitor
Visitor
2,266 Views
Registered: ‎04-08-2020

Regarding the byte count:

You are absolutely correct, I made a typo on the amount of bytes added. So the structure requires 64 bytes in total and we added that 48 (12*4) bytes padding into it.

Thanks for the correction!

0 Kudos
1,986 Views
Registered: ‎04-19-2019

Hi all,

I have incorporated the example into the project as written by abelo.
After that, the Endpoint address of xusb_ch9_storage.c was modified.

When I ran it and connected it to my PC with a USB cable, the COM port was detected in Device Manager.

However, when I try to open the COM port from RealTerm, RealTerm keeps not responding for a while (about 1 minute), and the error "The device connected to the system is not working" appears and I cannot connect.

Does anyone know a solution to this phenomenon?

Development environment is SDK 2019.1
The board used is Ultra96-V2.

0 Kudos
1,911 Views
Registered: ‎04-19-2019

Hi All

I don't know the cause yet, but when I changed the PC, it worked as expected. Both are Winodws10.

By the way, although it did not work properly in SDK 2018.2, it worked without problems when the version of the usbpsu library was replaced with v1.5.

0 Kudos