Library-Based Embedded Device Driver Development

Follow and star our public account to access exciting content

Library-Based Embedded Device Driver Development

Source: The Last Bug
Some friends asked me how to write excellent C code. This cannot be explained in just a few sentences. Excellent code is bound to be the crystallization of various programming techniques and design philosophies, so it requires step-by-step accumulation of methods to achieve a significant impact. Today, I would like to share this article about building a “library” concept with you all, where every sentence carries profound meaning~
If a device program is perfectly library-based, it means:
1. All engineers will incur minimal costs when porting or creating the device driver.
2. As the number of users increases, it has been tested and becomes increasingly stable, turning into truly public code.
3. The interface of the library (function names and their parameter declarations) remains unchanged. When all commonly used devices are implemented in a library format, it brings another benefit: the time spent on porting, creating, and modifying the application layer will be significantly reduced.
The seamless cross-platform porting of the application layer is not a myth. When all the peripherals it depends on are library-based across different platforms, implementing the application layer becomes as simple as writing Java code.
4. The library also means the safety of the company’s core code; the library code is only in the hands of core engineers, and even if the application layer program is lost, it does not matter.
5. Newcomers can get up to speed faster with these library-based projects. First, there are help documents for the library, and second, they do not need to concern themselves with low-level details, allowing them to focus on application development.
6. Providing customers with secondary development means you can hand over the libraries for hardware and peripheral drivers to customers for further development.
7. The library-based communication protocols will make communication system products safer, at least preventing damage from engineers who leave the company, such as in the case of RFID payment recharge.
8. And so on~
So, isn’t it cool to design and organize code in a library way~? At that time, these were the design goals of the library, but what effects can be achieved when it gets into the hands of engineers depends on their skill level~
Of course, some engineers may think that libraries can free them from tedious low-level driver work to engage in higher-level tasks.
To create a good library, the following conditions must be met:
1. Only .h and .lib files are provided to customers.
2. There are no #define statements in all .h files; compilation conditions for .lib files are just a joke.
3. There are no extern variables in all .h files; if there are, it means the system can only create one such device. For example, a buzzer driver with an extern variable means the entire system only allows one buzzer.
4. Comprehensive and detailed usage documentation. You can refer to the format of Keil’s help documents.
5. A simple demo program using the .h file for reference.
6. “Dynamic linking” of library code, in short, unused interface function code will not be included in the final binary by the linker.
7. Additionally, strive for platform independence; it should not rely on any registers or other platform-specific elements.
To achieve the above goals, libraries typically have the following characteristics.
1. Structure pointers.
2. A large number of callback function pointers.
3. Rich interfaces.
4. The library source code in .c files will be split into more .c files according to interface functions to minimize code space during linking.
Of course, everything has its two sides. If libraries were so simple and easy, wouldn’t everyone be able to create them effortlessly? Therefore, there are also some issues to consider.
1. It may slow down the device speed somewhat due to the additional layers of indirect addressing. However, for 32-bit machines, the convenience it brings is still acceptable.
2. It may consume relatively more code space, but trust me, for an entire medium to large system, it can actually reduce the code amount rather than increase it, because large systems have a lot of redundant and duplicate code. In my personal experience, the reduction is not insignificant; it reaches an unbelievable level.
In the early days, 8-bit machines could not effectively implement a perfect library, at least not for a cross-model low-level device driver library.
In recent years, with the rise of 32-bit machines, libraries have gradually gained favor among more engineers. The most fundamental reason for this is that the stack of the 51 architecture is statically compiled, and local variables and parameter stacks are also static, making functions non-reentrant. In contrast, most 32-bit machines use stack-based parameter passing. Of course, the slow speed of the 51 architecture is also one of the important reasons.
If you know object-oriented languages or Linux drivers, you probably understand what a good library looks like. A library is like a class in object-oriented programming, while the code for the low-level Linux driver is a world of function pointers and structure pointers.
The essence of C lies in pointers, which is perfectly illustrated within it.
Copyright belongs to the original author. If there is any infringement, please contact for deletion.

Recommended articles:

A multitasking management OS implemented in over 300 lines of code

Sharing an embedded software tools checklist!

Reply with1024 in the public account chat interface to access embedded resources; reply with m to view the article summary.

Leave a Comment