In this manual you will learn to create a shared library(.so) for your embedded ARM using Vitis. so you can use on Python on Petalinux.
Introduction
Designing shared libraries (.SO in Linux, or .DLL in Windows) can be highly beneficial in software development, particularly in the context of embedded systems, for several reasons:
-
Code Reusability: Shared libraries enable code reuse, allowing multiple applications or components to access the same set of functions or resources without duplicating the code. This leads to a more efficient and modular software development process.
-
Space Efficiency: In embedded systems, where resources like memory and storage are often limited, shared libraries can save space by allowing multiple applications to share the same code. This reduces the overall memory footprint of the system.
-
Version Management: Shared libraries provide a clear and structured way to manage software versions. When you need to update or fix a particular piece of code, you can update the library once, and all applications using it will automatically benefit from the changes. This simplifies version control and maintenance.
-
Interoperability: Libraries allow for better interoperability among different components of a system. They can serve as an interface between various software modules, making it easier to integrate different parts of an embedded system.
-
Encapsulation: Shared libraries encapsulate functionality, providing a clear API (Application Programming Interface) for interacting with the code. This abstraction helps in hiding implementation details and allows developers to focus on using the library without having to understand its internal workings.
-
Load-Time and Run-Time Flexibility: Shared libraries can be loaded at either load-time (when an application starts) or run-time (dynamically) based on the system's requirements. This flexibility can be crucial for optimizing system resource usage.
-
Security: Libraries can be designed to enforce security and access control, ensuring that only authorized components can use certain functionality. This helps in maintaining system integrity and data security.
-
Hot Patching: In some cases, shared libraries can be updated without needing to restart the entire system. This is particularly useful in situations where system downtime is unacceptable or challenging to achieve.
-
Language Independence: Libraries can be written in different programming languages, making it possible to leverage code written in various languages within the same embedded system.
-
Portability: Shared libraries can be moved from one system to another with relative ease, provided that the target system has the necessary libraries or can dynamically link to them. This can simplify the deployment and distribution of software on different embedded platforms.
-
Faster Development: Shared libraries can speed up software development because developers can focus on building higher-level application logic instead of reinventing low-level functionality.
However, it's important to note that designing and managing shared libraries also introduces some complexities, such as version compatibility issues and the need for well-defined APIs. Nevertheless, the benefits they offer in terms of code reuse, resource efficiency, and modular software design make them a valuable tool in software development for embedded systems.
Using shared libraries for accessing GPIOs or peripherals in embedded systems can offer several advantages over directly using kernel modules or sysfs for this purpose:
1. Portability: Shared libraries can be designed to provide a unified and consistent API for interacting with GPIOs and peripherals, abstracting the underlying hardware details. This allows you to write your application code in a more hardware-independent manner, making it easier to port the software to different platforms without rewriting the entire codebase.
2. User-Space Access: Kernel modules typically require kernel-space code, which can be complex and less accessible to application developers. Shared libraries operate in user space, making them more accessible to developers who may not be familiar with kernel programming, and allowing them to interact with GPIOs and peripherals more easily.
3. Easier Debugging: Debugging user-space code is generally easier than kernel-space code, and shared libraries facilitate this by keeping most of the code within user space. This can streamline the development and debugging process.
4. Flexibility and Customization: Shared libraries can be customized and extended to include additional features or modifications to suit your specific application requirements. This flexibility allows you to tailor the library to your exact needs without modifying the kernel or loading/unloading kernel modules.
5. Reduced System Instability: Kernel modules can potentially destabilize an embedded system if they contain bugs or incompatibilities with the kernel. By using shared libraries, any issues with the library are less likely to affect the entire system since it operates in user space and can be isolated.
6. No Need for Kernel Module Management: Using shared libraries eliminates the need to deal with kernel module management, such as loading and unloading modules and ensuring compatibility with different kernel versions. This simplifies the software deployment process.
7. Performance Optimization: Shared libraries can be optimized for performance since they operate in user space and can be tailored to the specific needs of an application. This level of control can lead to more efficient resource usage.
8. API Abstraction: Shared libraries can offer a higher-level, abstracted API that simplifies the interaction with GPIOs and peripherals, reducing the complexity of writing and maintaining low-level kernel code.
9. Application Isolation: By using shared libraries, you can isolate the behavior of your application from the underlying hardware and the kernel. This can enhance system stability and security by limiting the potential impact of application errors or vulnerabilities.
10. Licensing and Legal Considerations: Some kernel modules may be subject to open-source licensing requirements, which can be restrictive. Using shared libraries can offer more flexibility in terms of licensing and legal compliance.
However, it's essential to carefully design and maintain these shared libraries to ensure that they provide a stable and secure interface for accessing GPIOs and peripherals. Additionally, for some specific use cases or when dealing with highly specialized hardware, using kernel modules or sysfs might still be the preferred approach, as they offer more direct access to the hardware and can provide real-time capabilities. The choice between shared libraries and kernel modules depends on the specific requirements of your embedded system and the trade-offs you are willing to make.
Procedure
- Open Vitis and create a new library project.
-
Select the target platform you want to work with(your platform hardware).
-
Select Shared library and name it “test_shared”
-
Select either C or C++ as template.
-
Create 2 new files “foo.h” and “foo.cpp”, under src.
-
Write on the foo.h file the following.
#ifndef foo_h__
#define foo_h__
extern "C" {
int foo(int number);
}
#endif // foo_h__
- Write on the foo.cpp file:
#include <stdio.h>
extern "C" {
int foo(int number);
}
int foo(int number)
{
printf("Hello, I am a shared library\n");
printf("your return is %d\n",(number+1));
return (number+1);
}
-
Then build the library.
-
Once the library is compiled you will get a “.so” file which you now can use your shared library.. For this you need to copy the libtest_shared.so file to your rootfs using i.e WinSCP.
-
Now time to build test it with python.
#!/usr/bin/python
from ctypes import CDLL, byref, c_int
lib = CDLL("/home/root/libtest_shared.so")
data=lib.foo(10)
print(data);
-
you should see at the output:
Hello, I am a shared library
your return is 11
11