Combining the programmable logic fabric of a typical FPGA and the processing capabilities provided by ARM processor cores into a single chip, the AMD Zynq SoC devices can be used as a platform to build a wide range of embedded system applications. Dedicated logic structures can be designed in the PL to handle computationally intensive tasks while the PS can control the PL and provide user applications.
An endoscope is an example of a product that can make use of such capability. Video chains are implemented in the PL to improve the image signal from the scope camera and to provide extra features like video save, resolution change, color correction, etc. The processed video can then be sent to display sinks.
This is what I have been working on for the past few months and in this tutorial, I will show how to set up an application that runs on the FreeRTOS kernel in the Zynq PS.
FreeRTOSBefore we understand what FreeRTOS is, let's take a look at the three ways to develop an embedded system:
The difference b/w the three approaches lies in how the software portion is developed. The software can be separated into the user space (where the applications reside) and the kernel space (where the drivers and libraries reside). The size of the software increases from bare metal to Embedded OS.
FreeRTOS is an open-source OS dedicated to real-time applications. They provide the kernel space over which you can build your applications. The developer is able to tailor how the FreeRTOS kernel schedules its tasks. This allows applications to be built that have real-time constraints. An example of such an application could be performing USB transfers. An example of an application that is not suited for an RTOS could be running a full-fledged GUI.
Now that you have a brief understanding of the uses of an RTOS, let's dive into how we can set up FreeRTOS on the Zynq PS.
Hardware design in VivadoOur design is targeted to the Digilent Zybo Z7 board housing the AMD Zynq-7010 SoC device. Open up Vivado (note that I am using the 2022.1 version) and add the Zynq PS block in a newly created block design.
Customize the PS block to enable its UART 1 peripheral on the MIO pins 48-49. Also note that the other peripherals (GPIO, SD0, USB0, etc) are enabled by default since I chose to select the Digilent Zybo as my board while setting up the project. These have no impact on our application.
Save and validate the design. Then create the HDL wrapper, generate the output products, and generate the bitstream. Export the hardware platform information as an XSA.
Launch the Vitis IDE in a workspace folder and create a new platform project with the XSA. Select the freeRTOS kernel as OS domain.
After the platform project is created, modify its BSP settings to disable the xiltimer software library.
Then build the platform. Now create a new application project with the freeRTOS Hello World template.
Before explaining the main application code, I want to mention that the scheduler inside the freeRTOS kernel requires a timer to be configured at a default frequency of 100Hz for its operation. This could be a software or a hardware timer. I am relying on a hardware timer present inside the Zynq PS. That is why I have chosen to disable the software timer and its library in the BSP. Otherwise, it will conflict with the hardware timer when the application is run.
The main application defines two FreeRTOS tasks using the xTaskCreate() function:
Then it configures the hardware timer for a period of 10s after which it will expire.
Now it's important to clarify which hardware timer this design is using. Remember we have NOT enabled any such timer (TTC/SWDT) while customizing the Zynq PS in Vivado. We can look into the porting layer code present in the platform project.
The portZynq7000.c file contains information on how the freeRTOS kernel is being ported to fit the Zynq 7000 SoC-based devices. Upon opening we can see the following conditional definition:
So upon disabling the xiltimer, the design relies on generating timer interrupts using scutimer. This scutimer refers to the CPU private timer present inside each ARM-A9 core.
If you read portZynq7000.c in detail, you can see how the scutimer along with scugic is used to set up a timer interrupt.
After the timer is started, the freeRTOS kernel's scheduler is started using the call, vTaskStartScheduler(). The scheduler will start the two tasks defined above and the program will execute whatever code is defined inside those two tasks.
Final OutputAfter a successful software build, run the application on the board. You should see the following text getting printed in a UART console:
And that's it! You are all ready to start developing more complex programs on the freeRTOS kernel running on a Zynq SoC.
Comments
Please log in or sign up to comment.