Translate

Friday, 15 February 2019

How to create a standalone driver to handle a custom IP



Hi !

In this post we will create a standalone driver to handle our custom IP.

There are several goals here :

- Using a driver will encapsulate in it all the specific hardware knowledge of the IP, thus providing simple actions usable by the application without bothering with all the hardware implementation details.

- Having a driver ready for an IP will let the tools automatically import the driver into the BSP each time you use the IP in a design. No need to manually handle adding sources to the software project.

This post will be based on the low level software functions we wrote in the following post:

2.4 - How to create low level Software functions to handle a custom IP


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







Step 1 : Analysis of the generated driver template


When we used the custom IP generation wizzard, the tool provided us a driver template. In this section we will analyze its content.


Stage 1


The driver's repository is divided into 2 folders.

The first one is the \data folder which contains files to customize the driver's generation.

The second one is the \src folder which contains your C sources files.

This structure is mandatory, and you can only customize the \data files or edit your source files by following the rules for each of them.


Stage 2


The led_test_ip.mdd file in the \data folder

This file stands for Microprocessor Driver Definition.

It is associated to its own language with specific keywords, as defined in the UG1138 from the Xilinx's website.

The content of this file can be quite simple or it can be much more rich for complex drivers and advanced users. In our example it will be very light.


The led_test_ip.tcl file in the \data folder

This file uses the .mdd file to customize the driver depending on the .mss file options.

The main interest of this process, is to automatically convert the HDL generic parameters of the IP into C constants.

During the driver creation and insertion into the BSP, the tool will generate the led_test_ip_g.c file. The _g extension stands for generated.

This file contains a configuration table which contains a list of parameters for each instance found in the design.

The tcl file contains a first command xdefine_config_file where you list the parameter fields you need to get in the configuration structure. This structure will be available in the led_test_ip_g.c.

But to be compiled these parameters have to be declared in a .h file somewhere. This is done by the second command of the tcl file xdefine_include_file, where you list the same parameters, which will be inserted in the xparameters.h file and so be declared.

This process is very cool to let the driver access the IP's configuration parameters.

In the xdefine_config_file, be carefull, the IP name you provide has to be the same as the one you use in your C files ! As it will be inserted at the beginning of the variables' name !


Stage 3


The content of the sources depends on the complexity of the driver and the associated IP.

But the minimum structure is the main .c file, a .h file and the make file.

If you need more files then Xilinx provides a set of rules to follow if you want to keep the Xilinx's way of driver coding.

The led_test_ip.h file in the \src folder

The custom IP wizzard geneated a set of 4 registers as we asked. So they are in the HDL file and their offsets are automatically provided in the .h file.




The .h file will also provide macro functions for low level read and write access. These macros are only a renaming of the basic Xilinx's macros.




The led_test_ip.h file in the \src folder

This file is generated empty, so we will have to write the driver's functions in it.




Step 2 : Understand the driver's architecture


The driver definition in the Xilinx's way uses some rules, resources and organization that I will try to summarize in this section.


Stage 1


The first major element is the configuration structure, let's call it ip_name_Config. This structure is the one described before that is automatically initialized by the tool will the hardware parameters of the IP.

The second major element is the structure that contains all the running parameters for an instance of the IP, let's call it ip_name.

The functions that the driver will provide are initialisation functions and functions that shoud hide all the low levels actions and resources.

All the functions should only manipulate elements of the structures defined. And so, the functions only receive pointers on these structures. In some way the functions manipulate "virtual" resources. Thoses resources become real when in the application using the driver, variables are declared for the structures. If you declare several instance structure variables, you can handle several instances of the IP using the same driver.


Stage 2


Here is a synopsis of the overall architecture.




The sinit.c file is not mandatory. It is used by Xilinx in some drivers and not in others. The main goal is to isolate the initialize sequence, but you can do it in your application if you want.




Step 3 : Driver's file content description


In this section I will provide my code for this simple test driver.


Stage 1


For the led_test_ip_g.c file we can see the coherency between the VHDL input file, the tcl driver configuration file and the generated file.




Stage 2


For the led_test_ip_sinit.c file we can see that the first action is to get the Config structure with the LookUpConfig function and then pass both Instance and Config structures to the CfgInitialize function for initialization sequence.

The Initialize function beeing the one call from the application to initialize the driver's instance of the DeviceId instance of the IP.




Stage 3


The led_test_ip.c file is the main driver's file. It contains the CfgInitialize function for drive's instance intialization and all the functions that will provided to the application.

As this test driver only does a few things the CfgInitialize function does almost nothing.
The first thing is to set up the IsReady flag, it will be used to avoid doing initialization again.

Then it will initialize the base address of the custom IP, which is requiered for all physical read/write accesses.




Then we will find the fonctions for the application. They are associated to low level actions : set the LED ON, set the LED OFF and set the LED blinking !

The application does not have to care how it is handleds in the hardware of the custom IP.






Step 4 : Example application description


In this section I will provide my code for this simple test application.


Stage 1


For the main.c file we can see it is very ligth. An initialization step and then simple action requests and that's it !

And this is only because the driver does all the job !




Stage 2


So the SDK project view is the following. You can see that everything is in place and that the elf file is generated.




Stage 2


So if I launch the simulation, results will be the same as in the raw low level version




And that's it for now !







Post Conclusion
Now we have :

- Analyzed the goal of a driver and the standard structure for Xilinx compliant drivers,
- Detailled the content of our test driver,
- Detailled the content of our test application based on the driver,
- Seen that the driver is automatically provided in th BSP for the Hardware platform created with out test custom IP,
- Simulated the software to achieve the expected behavior of the software.

So now we have a clean driver for a standalone application.

Next I will try to do the same thing but for a Linux application !

No comments:

Post a Comment