Explore baremetal (C) applications on ZUBoard 1CG + UPDATE: First Look at the AES-ACC-DPEMMC-G DisplayPort & eMMC module

View table of contents ...  

RoadTest: Read the Reviews of the Avnet ZUBoard 1CG Development Kit

Author: dbkincaid

Creation date:

Evaluation Type: Evaluation Boards

Did you receive all parts the manufacturer stated would be included in the package?: True

What other parts do you consider comparable to this product?: This board is in-between a Digilent Zybo Z7 and an AMD Xilinx ZCU104.

What were the biggest problems encountered?: None, really. This board was a joy to evaluate.

Detailed Review:

Explore baremetal (C/C++) applications on ZUBoard 1CG

Larger applications are great, and they can have a lot of really nice features, particularly around areas where an operating system shines: USB support, storage options, networking, etc.

On the other hand users like myself enjoy running the board in a very low level configuration to control execution of the application precisely, and for this a baremetal application performance is unbeatable.

I will walk through the initial setup of my board and first projects. I will point out some observations that might help future users to save time.

Getting Started Guide (Out of the box demo)

The board ships with an application already set up on the Flash memory (QSPI)

Setup - Out of the box demo

  1. Hook up power (included), USB micro-B (BYO), Ethernet (BYO)
  2. Checked switch settings (they were already in correct position)
  3. Ethernet is on same hub as PC, to avoid any network subnet issues.
  4. Power board and attach tty terminal 
  5. image
  6. So far, so good!  Now using a web browser, I go to the http reported in terminal 
  7. image
  8. It worked right out of the box for me!
  9. Check that LEDs and peripherals work, temperature and pressure readings make sense
  10. image
  11. I used a calculator to sanity check the pressure reading, and it makes sense for where I live
  12. Out of Box demo is a success


Some initial observations

  • I had to flip around the Getting Started guide to look up the Board Diagram to find the power button -> It is beside the microSD socket.
    • image 
    • A picture in the step-by-step section (circle or arrow pointing) would have been helpful in 4.2 Getting Started Guide
    • Go ahead and point out reset here as well, we will be using it a lot
    • The silkscreen for these buttons is almost worthless, definitely would prefer something legible with human eye
      • currently only barely legible under magnifying glass
  • Soft switch for power-on is a new one (for me) on a board like this
    • To power off you have to hold down for 10 seconds.  It seems like much longer........zzzzzzzzz
    • Overall I like it but it's not great if you run headless and need to restart automatically.
      • This can be changed if desired by moving a resistor on the board.
      • There is a description of this adjustment and explanation of the power up circuitry on Page 40 of the Hardware User guide
      • image
  • I'm not the most savvy with terminals in Ubuntu, I use an application called 'screen'. The command to start is:
    sudo screen /dev/ttyUSB1 115200
    • the ttyUSBx might be different on a different machine, you might not need sudo depending on your config
    • It works well, but you will not be able to catch the powerup from Flash, only on reset to see the full report
    • It might have been nice if the startup report was sent again if user hit 'ENTER' button on the terminal.  
      • I cannot tell if it is even looking for terminal input... seems like it is just TX only
  • Initially excited about the MikroE Click compatibility, lots of options for boards but when I went to order: $20 shipping, ooof. Sparkfun is a distributor but price is a little higher and $10 shipping. Maybe if they put some inventory in their Amazon store I will pick up a MikroE click board for WiFi.
  • I realized most of my add-on boards are PMOD (Digilent), which is 3.3V compliant so I am thinking I will jumper in some of my PMODs to the Click port after I set up the initial projects.  
  • Ran board idling in the application for about 1 hour, the entire board is too hot to the touch.  It still works fine.  The board is cooled passively, but could probably benefit from a Low RPM fan cooling setup if running for long periods of time
  • I admit, this is a really neat web app, In the future I am going to explore an application like this as an interface for some of my future projects.


Vivado setup

  1. Launching Vivado on Ubuntu is not necessarily obvious after install
    1. source /tools/Xilinx/Vivado/2023.1/settings64.sh
    2. vivado&
  2. Happy to see the board can be pulled directly from library (did not have to copy files, but required internet access)
    1. image
  3. Zynq component is inserted into block design, and has a board preset available
    1. image
    2. Some details of the preset: 
      1. 33.333MHz reference clock -> 1200MHz Processor clock
      2. DDR4 set up for 533MHz (LPDDR4 1066)
      3. Some notes about the peripherals:
        1. Click port has pins assigned as board components with I2C, Reset, SPI, UART broken out for individual use.  I prefer this decision over a custom port, because it is easier to use a take control directly if you do not want to use a basic AXI peripheral.  For instance, you might want to use a reset controller for a Click peripheral to handle power on/off
        2. The 3-bit RGB are typically designed to be used in PWM mode to set brightness and color (mix), but I am not aware of a PWM AXI peripheral available by default in Vivado. You would have to write one. The GPIO attached would allow for the Zynq to modulate with AXI calls, but this is not a good way to handle a peripheral like this, you would rather send a setting and have the IP 'free running'. Avnet designed the board to safely turn on the RGB's because they have 3.3V with a 1kR resistor to keep the LEDs from burning out even at full power.
  4. Overall I think the board is set up well for my next steps
    1. image
    2. We are going to create a bare-metal PS application that toggles through the PL and PS LEDs, and reports button status, temperature, and pressure sensors
    3. If you are new to Zynq, a major difference between Zynq and standard fabric designs is that the Zynq (PS) is in charge of reset and clocks of the fabric
    4. Pressure sensor is an SPI port on PS (SPI_0)
    5. Discrete Temp Sensor is an I2C port on PL
    6. 1 push button on PL
    7. 1 push button on PS MIO 32
    8. For our PC terminal tty, we will use UART from the PS (through FT USB device)
  5. Don't forget to create an HDL wrapper for your block design (like I ALWAYS forget)
    1. image
  6. The beauty of Vivado on Linux: 90 seconds from block design to bitstream for a simple design like this
    1. image
    2. File-> Export Hardware : Include bitstream, as it is needed for Vitis to be able to reset and reprogram device in that environment. I like to put the .xsa in the base project directory
    3. Tools-> Launch Vitis IDE : I like to add a /Vitis directory to my Vivado project path, as my projects tend to be 1:1 between HW and SW design

Vitis Setup

  1. Create Application Project
  2. Create a new platform from hardware (XSA) tab -> browse to our exported hardware .xsa file.
  3. Default settings should Generate boot components and target the A53 core
  4. Give application project a name like Hello_ZUBoard
  5. Keep domain settings as default
  6. There should be a large list of example design templates, we will choose 'Hello World', as it will add some interface for our link between STDIN/STDOUT to UART
  7. Without changing any settings, let's build the project
    1. right click design_1_wrapper -> Build Project (wait for completion: 15sec for me)
    2. right click Hello_ZUBoard_system -> Build Project (wait for completion: 5sec for me)
    3. should be no errors in console window!
  8. We will confirm our UART is reporting on STDIN/STDOUT
    1. image
    2. navigate to platform.spr (open it)
    3. go to the Board Support Package under standalone_psu...A53
    4. click Modify BSP Settings...
    5. Default STDIN/STDOUT was psu_uart_0 for me, this is perfect
      1. note: if you target Coresight the stdout (printf) will report to a window in Vitis
      2. This is kind of convenient at times, but if you want to send input (stdin) then it is kind of a mess
  9. Update helloworld.c as follows:
    1. add a loop in main to continuously print
    2. while(1) { xil_printf("Hello World \r\n"); }
    3. Yes it is an infinite loop, and yes it is on purpose. Most embedded applications have infinite loops. We will just reset board when done.
  10. Don't forget to change the ZUBoard to JTAG mode, so that we can launch from Vitis using the debugger
    1. image
    2. Reset board after changing switch, after init one of the RGB LEDs will be white to indicate mode
  11. Right click on Hello_ZUBoard_system -> Build Project -> wait for it to complete
  12. Right click on Hello_ZUBoard [standalone_psu_core...] -> Run As -> Launch Hardware (Single Application Debug)
  13. On PC open terminal -> sudo screen /dev/ttyUSB1 115200
  14. Should see Hello World go zoom!
    1. image 
    2. To reset board use the RESET button (beside power button) to clear and return to JTAG idle.  Then use Vitis to Launch Hardware (same as above)
    3. I should add a note here that I did have some trouble during development with my UART terminal settings, but it was some issues on the PC side. I was able to clear it by fully power-cycling the ZUBoard so the PC could release the USB properly.


Vitis Terminal project

Now we want to integrate the peripherals into a baremetal project.  I will attach the application code directly, and make some notes on its use here

  • See the ZUBoard_app.c (zipped) for project source, it is attached to the review
  • PS and PL peripherals use different code in the application to setup and use. 
  • This full baremetal application should be helpful to determine the minimum required code to interact with each peripheral.
  • Sometimes it is easier to strip out than to add, I think most features are modularized well enough to help.
  • Note that I did not implement the SW4 bank input switches. I find these tiny switches to be problematic (I have broken them before, argh). If you want to include them in your design they are PS (MIO) pins 31, 39, 40, 44. The same setup process used for PS_button can be used for each of these signals.
  • The manipulation of counter value looks complicated but after it is dissected, it is hopefully obvious what I am doing.
    • First thing is to undertand the ternary operator in C -> result=(logic)?(value if true):(value if false)
    • Reminder that == is a logic 'equal to', where = is an assignment
    • Consider the 3 least significant bits (LSb's) to determine the value (counter&0x7) or (counter&0x3)
    • I use the next 2 'more significant' bits ((counter>>3) & 0x3) to select which section we are accessing: 1=PL_RGB0, 2=PL_RGB1, 3=PS_LEDs, 0=blanking time when all values are 0
    • Hopefully this will make it more clear how I use 'counter' to walk through the LED outputs
  • The pressure device also includes a temperature reading.  It always read much higher than the discrete temp sensor device.  
    • I do not think there is any issue with the device or my math, temperature deltas are common in this type of environment
  • Ambient / Passive cooling
  • image
  • PC Fan blowing across board
  • image
  • There is a 'beef' I have with the AMD/Xilinx toolchain on their Zynq devices.  The USB device (FTDI) does not consistently recover from physical reset and/or debugger reset.  It sometimes takes 2 or more tries for the software to recognize the device and reprogram/restart the application.  I have not found a clean way to workaround this, but I would love to know one.  This is not a complaint about ZUBoard specifically, I have worked on 4+ Zynq dev boards from 4 different vendors, and they all act this way.  
  • Undocumented-ish feature! A/D Converter is on the board, Connects to J5 pin 1 : CLICK_AN
    • MCP3201T A/D Converter SPI Clk < 1MHz
    • I did not implement, but I did have an idea how to use existing IP to implement without too much trouble
      • AXI QSPI peripheral IP only supports /16 (?) on clock rate, so we need to drop the AXI clock way down to get to 1MHz.
      • Add another PL clock output from the Zynq of <16MHz
      • Add an AXI clock converter to the design and run the AXI communication from the main subsystem (100MHz usually) to the <16MHz domain, then use the /16 setting on QSPI IP

Closing remarks

I hope that this review/tutorial helps new users to acclimate to the powerful Zynq architecture.  I am excited to deploy some more advanced projects on the new ZUBoard 1CG.

I do like the Click and Syzygy connectors, and I hope that as adoption begins to ramp that they will begin to have a good selection of low-cost add-on boards available. 

I would LOVE to see an actual USB3.2 (10Gbps) device-mode deployed on the Syzygy TRX-2.  

UPDATE: First Look at the AES-ACC-DPEMMC-G DisplayPort & eMMC module

Very happy to continue my journey with the ZuBoard 1CG eco-system, I had the opportunity to try out the new add-on module 

Hardware used in this review

  • Avnet ZuBoard 1CG
  • Avnet AES-ACC-DUALCAM-G add-on board
  • Avnet AES-ACC-DPEMMC-G add-on board
  • >=16GB microSD Card
  • Ethernet cable, Keyboard, and Mouse
  • USB 2.0 cable (A to micro-B, this is probably the most common cable type)
    -AND-
  • DisplayPort capable monitor
  • MINI DISPLAYPORT to DisplayPort cable
    -OR-
  • (from Amazon) BENFEI Mini DisplayPort to HDMI, 4K@60Hz Active Mini DP to HDMI Adapter (Thunderbolt Compatible) with MacBook Air/Pro, Surface Pro/Dock, Monitor, Projector
    • Section with important discussion on this later, recommend to check this before ordering
  • (from Amazon) Suckoo replacement HDMI Female to USB3.0 Male Audio Video Capture Card Live Streaming Recorder MS2130 HDMI2.0 Capture Card Device Connection USB Computer Host Laptop Docking Adapter Converter
  • HDMI cable


Initial Setup

This RoadTest UPDATE is specifically for the DisplayPort feature of AES-ACC-DPEMMC-G board. I will assume familiarity with the ZuBoard and the DUALCAM add-on, we will follow some instructions from that kit.

The DisplayPort module is capable of extending the DUALCAM reference design, so we will use this to get going. I will go through the setup and show some of the things I learned along the way.

In the AES-ACC-DPEMMC-G box:

I found there is also a second web page at http://avnet.me/dpemmc-pdp, with some additional documentation, I expect this page might merge at a later time. It says there is a reference design available, but it links back to the first page again. Actual example design is part of the documentation for ZuBoard, it is also linked below as part of instruction.  https://hsio-dualcam.readthedocs.io/en/latest/index.html

Important: Board connection for DisplayPort is a 'MINI DISPLAYPORT' version, so make sure to check this if a cable is required.

Board Features

  • 32GB eMMC (WOW!)
  • miniDP output up to 4K@30fps
  • 2 GPIO LEDs

Tech Docs on site as of 5/31/24

  • Product Brief
  • Board BOM
  • Schematics

The HSIO-dualcam is available for the ZuBoard 1CG, and it has a reference design available from Avnet.
https://hsio-dualcam.readthedocs.io/en/latest/index.html

Important: Requires at least 16GB microSD card

The image is pretty large: 12GB file, so plan for the download
Following instructions on the page linked to move image onto microSD card, be patient again. It took a little over 6 min to flash and validate my card using balenaEtcher and a good PC.

Connect as shown, and use the added labels as reference.

image

For future reference, confirm the Jumpers on the DualCam module are configured as shown

image

Getting Started

Continue to follow the guide for HSIO-dualcam until you get MobaXterm X11 connected, and can see the image pop-up from

cd ~/avnet_dualcam_python_examples
python3 ./avnet_dualcam_passthrough.py

The SD card image loads avnet-zub1cg-benchmark by default, but we would like to load avnet-zub1cg-dualcam as default, so we will do this:

nano /etc/dfx-mgrd/default_firmware

Note: change "avnet-zub1cg-benchmark" to "avnet-zub1cg-dualcam"

We can now run the demo after boot and login using MobaXterm over ethernet (so that X11 displays locally)

(from avnet examples folder)

python3 ./avnet_dualcam_passthrough.py --fps
get about 10FPS with dual 640x480 cameras

python3 ./avnet_dualcam_passthrough.py --mode primary --fps
single cam 640x480, about 20FPS

python3 ./avnet_dualcam_passthrough.py --mode dual --width 320 --height 240 --fps
dual cam 320x240, about 60FPS

python3 ./avnet_dualcam_passthrough.py --mode primary --width 320 --height 240 --fps
single cam 320x240, about 60FPS

Adding native DisplayPort

Now power-down and connect my miniDP to HDMI adapter and ... nothing. I ran some diagnostics using
> modetest -D fd4a0000.display
and it showed that the display did not send any information back about screen size supported.
I tried a few workarounds with settings but found no solution. I was confident it would work because of another post where they had deployed Linux to the eMMC

I had some recollection of a blog I read about DisplayPort problems <I would love to cite, but I cannot find it!> I read where they mentioned they specified use of an 'active' DP to HDMI converter.  My converter didn't explicitly say this, so I ordered an 'active' version of the device (it is linked at the beginning of article).
Using this new 'active' miniDP to HDMI I got output!  The demo will output on DisplayPort as if you had connected a terminal through UART.  Then I connected my keyboard and found I could interact with the terminal just like I had connected through COM port with a terminal application.

Stand-alone OS operation with GUI

To get to the GUI, have monitor and keyboard / mouse connected when booting :

do not enter password at prompt!

Leave it for about 5 seconds and the system will launch an OS GUI.

The board launches a full GUI where I could open terminal and run the Python demo again, it will open a vision window within the OS GUI. There even seems to be a modest performance increase:

Default dual cam 640x480 ran at 16FPS instead of 10FPS through MobaXterm. The performance scaled up in all the prior test-cases.  In short, it runs might higher performance through native DP than what is possible through ethernet.

imageimage

UPDATE Conclusion

With the addition of the DP module, I have the building blocks of a very nice and programmable embedded system:

  • Lightweight OS
  • HID (keyboard and mouse) support
  • Graphical environment all running locally with DisplayPort output, or over ethernet if desired
  • I also have the option to move the build to eMMC to utilize the storage
  • For user interaction, the DisplayPort is the highest performance interface for display (it outperforms ethernet by a solid margin)


Thanks to these articles for reference:

Anonymous
  • Apologies for the 6-month reply, but I didn't know that I had a response and I completely forgot that I had added a comment here.  Back then, I did not know a lot about PS structure for SoC.  I figured it all out eventually, as I never knew much about the SPI core and usually wrote my own SPI.  For other microcontrollers, it was easier for me to understand.

  • Hey thanks for reaching out.  The documentation of the SPI core explains a bit about this.  You have to use a divisor to slow down the protocol to match the peripheral.  In this case the peripheral could accept up to 8MHz so we divided by 32 to get as close as we could

  • Thank you for the code.  I just got the board and am new to Xilinx.  I do have a question about the SPI sensor.  On line 154 of the C code you provided, you set the prescaler.  On the next line, you have a comment that says 187.5 / 32.  Where did that 187.5 come from?  You set the board speed to max, so is the 187.5 the max speed of SPI at that core speed?  Thank you.