Translate

Friday, 12 April 2019

Very Low Level access with Peek and Poke



Hi !

Software access to Custom IP's registers under the Linux world can be done in so many ways !

This large choice of possibilities leaves beginners quite lost on how to start !

In this post we will start slowly and very easilly !

Let's do it old school using PEEK and POKE commands.

Even thow they are based on mmap that will see later in another post, these comands are still the same ! I read or write a physical address directly.

As this post is quite long, here are the main sections of this post for a quick jump :







Step 1 : Activate the PEEK and POKE commands in PetaLinux



Stage 1


The activation of the PEEK and POKE commands is done during the configuration step of the Rootfs in the PetaLinux tool.

So go the project's folder and use the following command.




Stage 2


This opens the configuration menu.

Then go to the apps menu.




And select the peekpoke application.




Then press escape several times to get out of the configuration menu.

Before leaving, you will be asked to save the modifications. Select Yes.




Then the configuration modification is done.




Now that configuration is done, you have to use the build comand again to generate the files.


Stage 3


The PEEK and POKE commands are in fact two Linux applications which source files can be found in project-spec/meta-user/recipes-apps/peekpoke/files/.

You'll see that these source codes are based on a system call named mmap (Memory Map).

You have to open the virtual file /dev/mem of the system memory, then make a mmap system call to the /dev/mem file to gain access to a physical address from the user space. More precisely, mmap will map an entire physical memory page, then your pointer can manipulate every offset in this memory page.






Step 2 : Use the PEEK and POKE commands in PetaLinux



Stage 1


First step here is to load the files to the MiniZed board.

Like the following previous post, we will use the JTAG commands from the PetaLinux tool.

2.7 - Generate a basic Linux over the custom IP

And then we will try the PEEK and POKE commands in a Putty terminal.

When in the terminal, try the commands to see if they are available.




OK, everything is ready !


Stage 2


Now, we have to find where are located the registers to access. This is the absolue physical address of our custom IP.

You can find the information :

- In the device tree file pl.dtsi, or
- In the VIVADO project, with the address mapping of the Block Design Editor.

So, for us it is 0x43C0_0000.


Stage 3


Now, to force the output led to ON, we only have to do the same steps as in the LED_TEST_IP_SetLedOn function of our driver.

Which gives.




And there you go !

The led is ON on the MiniZed board.


Stage 4


Now, to force the output led to ON, we only have to do the same steps as in the LED_TEST_IP_SetLedOff function of our driver.

Which gives.




And there you go !

The led is OFF on the MiniZed board.


Stage 5


Now, to force the output led to BLINK, we only have to do the same steps as in the LED_TEST_IP_SetLedBlink function of our driver.

Which gives.




And there you go !

The led blinks on the MiniZed board.










Post Conclusion
Now we have :

- Configured our Linux to have the PEEK and POKE commands available,
- Used the PEEK and POKE commands from the terminal to control the behavior of our custom IP.

For now we did not write a single line of software !

But yet with these commands we can control from the embedded Linux the registers of our IP, it can be usefull to make some debug tests. You can even write scripts to chain commands.


Friday, 5 April 2019

Generate a basic Linux over the custom IP



Hi !

In this post we will use what has been done for the Zynq standalone design to test our custom IP's driver. If you've missed it, have a look to this post and the previous ones.

2.6 - Run the test driver on the MiniZed board with a standalone Zynq design

The goal of this post is quite simple, generate a basic Linux for the Zynq core associated to the PL bitstream which includes our custom IP.

This will be done using the PetaLinux tool installed in the previous posts. That a look over there:

1.6 - How to install PetaLinux


As this post is quite long, here are the main sections of this post for a quick jump :







Step 1 : Import the project under the Linux environment



Stage 1


The previous posts used the VIVADO tool in the Windows environment to generate the Zynq project that we will re use.

So the first thing to do is to copy the VIVADO project and its dependency (our custom IP library) in Ubuntu. For that we use the shared folder.




Stage 2


Now we are going to open the project in VIVADO in the Ubuntu environment to check that everything is ok.

Open the Virtual box, Launch the VM, Log in Ubuntu.

Then I will copy the files into my user space under /home/mtvl/fpga/.




Then Launch VIVADO and open the test_proj_zynq project.

First thing to do, check that the dependency to the custom IP library has been automatically updated to the right folder.




Ok, so everything is set properly.


Stage 3


Now we are going to regenerate the bitstream, to check that everything is fine under Ubuntu.

Click on Generate Bitstream.

Set the number of jobs and click Ok.




The generation flow will execute until it is done.


Stage 4


Now the last and most important step, the Hardware Platform generation !


Good to know :

The Hardware Platform generation will provide a HDF file. This file is a container that will include all the major elements for PetaLinux tool to generate a Linux that contains everything to access our custom IP.




You can check that the design_1_wrapper.hdf file has been generated or updated in the /test_proj_zynq/test_proj_zynq.sdk folder.

You can close the VIVADO tool.





Step 2 : Create the Linux using the PetaLinux Tool



The PetaLinux tool is a very powerfull tool that make things quite easy !

The tool provides a sequential list of tasks in which you select the ones you need.

The workflow is the following:




Stage 1


So the first step is to create the Hardware Platform.

That's what we've done for the Zynq Standalone project.

But for Linux, there are some specific constraints that we have to add !

The Linux to run expects the following resources:

- One Triple Timer Counter TTC
- An external memory controller with at least 32MB of memory (we'll use the DDR of the Minized)
- An UART for serial console (which is the minimum mean of communication with the Linux)

Then some other resources are optional but usefull for other tasks:

- A non Volatile memory for storing boot ressources (QSPI, SD, MMC)
- An Ethernet controller for network access

I made a copy of the test_proj_zynq folder into a test_proj_zynq_linux folder.




Stage 2


Now let's open VIVADO to edit the Zynq core and for now, only add the required resources.

For the first element, the TTC, go to MIO configuration, click on the Timer 0 and select the pre defined pins MIO.




For the DDR controller, everything is already set up thanks to the MiniZed board file configuration.




And for the UART we have first to look to the one used on the Minized board.

The schematics of the board show that it is the UART1 on the MIO[48:49] pins.

Go to MIO configuration, click on the UART 1 and select the pre defined pins MIO[48:49].




Then regenerate the BD wrapper file and launch the bitstream generation.

Once it is done, launch the Export Hardware to update the HDF file.


Stage 3


So now let's create the PetaLinux project.

I will place it in the /home/fpga/test_proj_petalinux folder.

Open a terminal and go to /home/fpga.

Create the project with the following comand:




The command details :

- petalinux-create : petalinux resource creation
- -t project : specifiy which type of PetaLinux ressource to create (Project / Application / Module)
- -n test_proj_petalinux : in our case we specify the name of the project
- --template zynq : request to create a project with a Zynq predefined template (MicroBlaze / Zynq / ZynqMP)


Stage 4


As we use a custom hardware, we are now going to initialize the project using the Hardware Description file we generated.

First thing to do is to go to the PetaLinux project's folder.

As we are inside the PetaLinux projet, we have to provide the path to the HDF file. The command is the following:




The command details :

- petalinux-config : Initialize a PetaLinux project (only for custom hardware projects)
- -get-hw-description : Must provide the path to the folder containing the HDF file. Either the path is provided and you have to be in the project folder, either the path is not provided and you have to be in the HDF file folder.


This will launch the configuration menu.




This a very interesting menu. It can let you configure your project, but it can also let you check what is currently configured. For example you can check in Subsystem AUTO Hardware Settings what is the current UART for console.

Execution of the initialization can last several minutes.




Stage 5


Now we can build the projet.

So go inside the PetaLinux project's folder and type the following command:




The execution provides a warning but it can be ignored, see AR# 71110.

As you can see, the build step can be quite long, for me it took about 40 minutes.

The build step is very important because it provides a lot of things.


Good to know :

The build step will generate:

- A log file in test_proj_petalinux/build/build.log
- A DTB (Device Tree Blob) file,
- A FSBL (First Stage Boot Loader) file, which can be configured to not be generated,
- U-Boot,
- The Linux Kernel.

All these files are generated in the test_proj_petalinux/images/linux folder.
The tool makes a copy of these files in the /tftpboot folder to be ready to download to the board.






Step 3 : Analyze the generated content of the PetaLinux project



Stage 1


One thing interesting to check is to see if our IP has been integrated in the hardware definition. This means, is our IP part of the device tree generated ?

Well, this is the case. The folder test_proj_petalinux/components/plnx_workspace/device-tree/device-tree contains all the Device Tree elements.

The pl.dtsi stands for the Programmable Logic Device Tree Include, which should describe the content of the FPGA. So everything is ok, our IP is described.




This IP is expected to be compatible with the xlnx, led-test-ip-1.0 driver !


Stage 2


Another interesting thing, is to see what are the inputs to the PetaLinux project. The test_proj_petalinux/project-spec/hw-description folder contains these inputs.




There we can check that are available:

- The HDF file which describes the custom hardware,
- The bitstream  to configure the PL, generally used by the FSBL,
- The ps7_init files to configure the ARM peripherals,
- And a drivers folder that contains the driver for our custom IP.

The only thing is that the driver content is the standalone one, we'll have to see how to handle it to make it compatible for Linux !!






Step 4 : Load our Linux onto the MiniZed board



Stage 1


Now that the PetaLinux tool has produced all the needed files, let's configure the board.

To bring the board to a configured state, a lot of stages have to be executed, here is the Linux Boot Process on a target platform.




A very important point to have in mind is that for each steps several solutions are available to do it !

As we are using the PetaLinux tool we will start by using the PetaLinux resources for booting the board.


Stage 2


As we are at the beginning of the design, we will use the JTAG as a straightforward tool to make the first tests with the board. But we will see that it is not the right solution for transferring large files, it takes too much time !

So, first thing to do check that the MiniZed board is configured for JTAG boot.




Stage 3


We will use the PetaLinux command to load and configure the bitstream file into the PL.

Don't forget to activate the VM's serial port (Xilinx JTAG + Serial) when you power up the MiniZed board.

Go to the PetaLinux project folder and use the following comand:




This command uses the system.bit file located in the /test_proj_petalinux/images/linux/ folder.

The Done Led of the MiniZed board shall be activated after about 20 seconds.


Stage 4


We will use the PetaLinux command to load and run the u-boot executable file from the PS.

Open a Putty terminal to have a look at the Linux Console terminal.

Go to the PetaLinux project folder and use the following comand:




The bitstream has to be loaded on its own, but the command launches all the following tasks :

This command uses the zynq_fsbl.elf file located in the /test_proj_petalinux/images/linux/ folder. This will load the file in memory and execute it to configure the ARM core.

This command then uses the u-boot.elf file located in the /test_proj_petalinux/images/linux/ folder. This will load the file in memory and execute it.

Once it is done we get the U-Boot execution prompt on the Putty terminal.




We can see that U-boot tries to load the kernel from the QSPI flah memory, but as it is not programmed, it fails.


Stage 5


We will use the PetaLinux command to load and run the Kernel file from the PS.

Open a Putty terminal to have a look at the Linux Console terminal.

Go to the PetaLinux project folder and use the following comand:




The bitstream has to be loaded on its own, but the command launches all the following tasks :

This command uses the zynq_fsbl.elf file located in the /test_proj_petalinux/images/linux/ folder. This will load the file in memory and execute it to configure the ARM core.

This command then uses the u-boot.elf file located in the /test_proj_petalinux/images/linux/ folder. This will load the file in memory and execute it.

This command then uses the system.dtb file located in the /test_proj_petalinux/images/linux/ folder. This will load the file in memory and provide the Device Tree to the Kernel.

And then, this command uses the zImage file located in the /test_proj_petalinux/images/linux/ folder. This will load the file in memory, it will be uncompressed to get the File System and the Kernel. Finally the whole Linux system can be launched !

Once it is done we get the U-Boot execution prompt on the Putty terminal.

As I said, it is quite long, for me it took 4'35 to complete. Obviously you won't use this when you need to made debug on this section !

Then we get the log of the Linux initialization.


Good to know :

UPDATE !!


I changed my USB Cable and there was a miracle !!!

The loading time reduced from 4'35 to 35 seconds !!!

So the USB cable's quality can change your life.




To log in use root:root.


Stage 6


We can see if our custom IP is still seen in the device tree with the command :




So yes, our led_test_ip is still available in the hardware.

We've done everything we had to for the hardware side.

Now we can do so much things in the software side !!!








Post Conclusion
Now we have :

- Customized the Zynq core IP to add the Linux neccessary resources,
- Checked the VIVADO project generation under Ubuntu,
- Checked the Hardware Platform generation under Ubuntu,
- Created the PetaLinux project,
- Generated the customized Linux,
- Booted the Linux system on our MiniZed board.

This is it. We've generated a Linux that knows our custom IP as a new physical peripheral.

Now we have to write some software to use our custom IP !