Apex Universal Library Demo Illustrating Open and Close of a Device
The purpose of this tutorial is a simple walk through initializing and terminating the library. We are assuming the kernel module has already been installed. Further, it will attempt to open and then close a device. If the application completes successfully then we know that the library and underlying kernel module are communicating correctly and subsequent more advanced applications will work. The demo_basic application does not verify software revisions and that is covered under a future advanced tutorial.
In this discussion we will go over demo_basic which is a very simple C example of initializing the library/kernel-module, opening a device, closing a device, and terminating the library/kernel-module. This discussion assumes that you have the kernel module installed (insmod) and the demo_basic source is ready for compilation. We are also assuming that the Eclipse workspace is all setup and is in its original form; if this is not the case, simply extract a new copy to another folder of your choice. More about the kernel module install and Eclipse workspace are found under separate tutorials.
There are two ways of demonstrating this application: (i) using Eclipse and the gdb debugger and (ii) using the make files to compile and then run the application in a terminal. The Eclipse project, when building the application, will automatically generate the make files for us.
We will begin with demonstrating using the Eclipse IDE. Make sure that the demo_basic project is open, right click on the project and select "build project". Note that the project build project configuration is set to _Out_Debug which will build a debug version of the project to _Out_Debug folder under the current project folder.
Next, we can run the debugger and single step through the project observing line-by-line. The output, found in the console of the Eclipse IDE will be the same as the command line output as discussed below.
Take a look within the _Out_Debug folder. What you will see is the compiled application demo_basic. Further, you will see makefile, objects.mk, sources.mk and subdir.mk which are auto-generated when building the project and can be used for compilation at a terminal.
Next, we will run through building and running the application from the terminal.
- move to the folder "~/aes_ws/demo_basic/_Out_Debug" (without quotes)
- execute the make file: "make clean" (without quotes)
- execute the make file: "make all" (without quotes)
- now run the program: "./Demo_Basic" (without quotes)
Here is an illustration:
user@Ubuntu32vb:~/aes_ws/demo_basic/_Out_Debug$ make clean <-- remove previous build
user@Ubuntu32vb:~/aes_ws/demo_basic/_Out_Debug$ make all <-- rebuild the application
Building target: demo_basic Invoking: GCC C Linker gcc -L../../aul_tree/_Out_Library_Static_Application_Debug -o "demo_basic" ./demo_basic.o -lauldebug Finished building target: demo_basic
user@Ubuntu32vb:~/aes_ws/demo_basic/_Out_Debug$ ./Demo_Basic <-- run the code Library name = libauldebug.a <-- Line 128 of demo_basic.c AUL_Initialization successful <-- Line 161 of demo_basic.c Driver name = mod_auldrv <-- Line 180 of demo_basic.c AUL_Device_Open successful <-- Line 234 of demo_basic.c AUL_Device_Close successful <-- Line 258 of demo_basic.c AUL_Termination successful <-- Line 284 of demo_basic.c user@Ubuntu32vb:~/aes_ws/demo_basic/_Out_Debug$
Now, lets walk through the output to understand what is happening at each step. Refer to the source file demo_basic.c as we discuss. You might want to have the demo_basic.c file in one screen while reading this tutorial in another.
The first printf() statement on line 128 reports the library that is statically compiled with the demo_basic application. The library name is retrieved by using the AUL_Library_Name() function. It is used to aid the developer in determining which library, auldebug.a (debug) or aul.a (release) is statically compiled into the application. The AUL_Library_Name() function is just a reporting mechanism so that a developer can confirm which library is actually being used in the application, nothing more.
The next step is to both initialize the library and open the underlying kernel driver as shown on line 155 of the source file. This uses the AUL_Initialization() function. Note that the hardware_definition_file_name parameter is always set to NULL; this is a carry-over from previous drivers to maintain compatibility. If an error is reported, it is very likely that the mod_auldrv kernel driver has not been installed or installed properly. The function AUL_Error_String() will return a human readable error code and is illustrated in line 158 of demo_basic.c file. Upon successful completion of this function the kernel driver will be opened and the library ready to accept device related functions/commands.
Now that the kernel driver has been opened successfully, we can inquire about the name of the driver. Just as the library AUL_Library_Name() function returns a name, we can obtain the name of the kernel driver that we have opened. The function AUL_Driver_Name() is used exclusively as an aid to the developer to confirm that we are connected to the correct kernel driver.A device is defined as a board such as an STX104 or Tracer module. The device name is defined during insmod process. Refer to kernel driver tutorial that discusses how to install (insmod) the kernel driver.
Focusing on lines 213 through 234 of the demo_basic.c file we are using AUL_Device_Open() function to open a device. if the device name was included in the command line in which the application was started (second argument in the argv array), then that device name is preferentially used, otherwise it defaults the device named "stx104".
// Example #1: running demo_basic using default device name found on line 220.
// Example #2: running demo_basic using an over-riding device name. Note
// this device name provide during insmod
user@Ubuntu32vb:~/aes_ws/demo_basic/_Out_Debug$ ./Demo_Basic stx104
The function AUL_Device_Open() will return a board descriptor number that is used in all subsequent device related functions. The board descriptor, which is just an integer value, is a fancy term for an index into a list which resides within the library and kernel driver. The board descriptor is only valid if the AUL_Device_Open() returns successfully (i.e. returns SUCCESS or 0 value).OK, now that we have reached line 234, the demo_basic application is reporting a successful device open. At this point, we can start performing device related tasks like gathering inputs or setting outputs. This will be illustrated in subsequent tutorials.
Now, rather than going into more depth about the particular device we have successfully opened, we are going to now reverse the steps we just did above to illustrate that we can open the library, open a device and now close a device. The function AUL_Device_Close() performs the device close operation. Refer to lines 257 and 258 in the demo_basic.c file.
In order to properly close the device we have to pass the board (or device) descriptor to this function. For any function that reads/writes to a device, we must also pass the board (or device) descriptor. The board descriptor is given upon a successful device open function call.
Finally, it is time to close the kernel driver and the library. Here we use the function AUL_Termination().
The AUL_Termination() function only needs to be called if the AUL_Initialization() function was completed successfully. If an error occurs we can use the same AUL_Error_String() function to retrieve a human readable form of the error code. The termination has completed successfully.
You may have discovered that all of the functions we discussed above are located in the aul.h header file. In the Linux case, the macro AUL_DLL_API and AULCALLCONV will default to the following:
#define AULCALLCONV __attribute__((stdcall))
The driver/library is designed to support multiple OS targets so this is a way for us to build the correct function signatures. Further details on these macros will be covered in more advanced tutorials.
The demo_basic program provides a very simple way to test how an applications connects up with the AUL library and driver. It provides simple reporting of the actual kernel driver and precompiled library names. I hope that you have enjoyed this detailed introduction.