. Net micro framework dynamic calling of C/C ++ underlying code (Principles)

Source: Internet
Author: User

.. Net micro framework is different from the wince system. From the perspective of application development, only C # development is supported (VB is supported since v4.2... net, you can also use EVC and other tools for C/C ++ development. For the. NET micro Framework Platform, because C # And other. NET languages are hostedCodeThe system needs to explain and execute the intermediate language. Therefore, compared with the native C/C ++, the efficiency is discounted, this is difficult to implement for applications with high real-time requirements.

If you need to use. net micro framework to develop some highly real-time applications. The common practice is to start with the underlying porting kit and write a driver with C/C ++, then encapsulate an interface that can be called by C # for developers (see micro framework InterOP function implementation). However, you must be familiar with this method. net micro framework system transplantation, in addition to a set of system source code at hand, not only need to be familiar with C/C ++, but also need to be familiar with C #, In order to need to combine up and down to complete the relevant functions. From this perspective, it is too harsh for general developers, not only demanding technical capabilities, long development cycle, but also the need to re-compile the firmware to upgrade the original system.

A few years ago, I had been thinking about using DLL dynamic calling on Windows or wince platform to implement. Net micro framework dynamic calling of C/C ++ code. So I also read a lot of PE file structures later.ArticleThere are also some books on compilation principles, but it is difficult to implement this technology due to insufficient knowledge reserves.

In. net micro framework system migration and development process, I deeply feel that it is quite troublesome to encapsulate a proprietary hardware driver interface, therefore, inspired by the streaming-driven development on the wince platform (see my first wince driver I wrote earlier), I encapsulated a set based on. net micro framework streaming interface (based on this interface, I have developed the dht11 Temperature and Humidity module, the ultrasonic module and the dog driver.ProgramIn the future, I will post a blog post). Its C # language interface is as follows:

 Public   Sealed   Class  Generalstream {  Public  Generalstream ();  Public   Event  Generalstreameventhandler notice;  Public   Int Close ();  Public   Int Iocontrol ( Int  Code );  Public   Int Iocontrol ( Int Code, Int  Parameter );  Public   Int Iocontrol ( Int Code, Byte [] Inbuffer,Int Incount, Byte [] Outbuffer, Int  Outcount );  Public   Int Open ( String  Name );  Public   Int Open ( String Name, Int  Config );  Public   Int Open ( String Name, String  Config );  Public   Int Read ( Byte [] Buffer, Int Offset, Int  Count );  Public   Int Write ( Byte [] Buffer, Int Offset, Int Count );} 

It also provides an Event Notification interface, which provides more flexible support for various hardware driver development.

With this stream interface, it generally provides proprietary hardware underlying functions for the upper-layer C # language, so you do not need to write interface-related code, directly write the relevant C/C ++ code, and then compile the link.

As a result, I suddenly thought about whether to dynamically load the driver developed based on the stream interface.

Initially, the stream interfaces and various stream drivers I developed were in one project and eventually compiled into an OBJ file. Later, considering the ease of debugging and maintenance, separate the stream interface part from each stream driver. Each stream driver is a separate OBJ file.

Inspired by er_config and er_dat, during compilation, they can specify the starting position of compilation and can be compiled into a bin (or hex) file independently, therefore, a stream driver can be compiled into a binfile independently, so that it can be deployed separately.

Since the interfaces of each streaming driver are consistent, we can naturally think that this binfile can be replaced theoretically. For example, at the beginning, we loaded the streaming driver of the function, we can also replace it with the streaming driver of function B as needed.

So how do users develop this relatively independent stream driver module?

If it is still based on the. NET micro framework, the entire porting KIT development environment is simply a nightmare for general developers. It takes a long time to familiarize themselves with the environment by setting up the environment.

Therefore, the best way is to use the MDK development environment and develop the driver based on a simple streaming Driver Module project.

Let's wait a moment. We should not consider how to build the MDK development environment for the moment. Let's take a look at our ideas, even if we solve the development and compilation problems, but the most important thing is to solve the problem of how the stream driver module interacts with the host (tinyclr.

There are two problems to be solved. First, how does the host obtain the interface address of the streaming driver module? The second is how the streaming driver module accesses host resources (we access system resources through the so-called API interfaces on Windows or wince ).

The first question seems simple, but I have made many detours.

First, it is easy to think that we store the pointer of the stream-driven function interface to a variable, as shown in the following code:

 
ConstIgeneralstream g_generalstream_userdriver ={&Generalstream_open‑userdriver,&Generalstream_open2_userdriver,&Generalstream_close_userdriver,&Generalstream_iocontrolpolicuserdriver,&Generalstream_iocontrol2_userdriver,&Generalstream_read_userdriver,&Generalstream_write_userdriver ,};

We only need to know the address of g_generalstream_userdriver and the address of each function interface. In other words, we can specify the address of the g_generalstream_userdriver variable during compilation. However, the problem arises. If I specify the address of the g_generalstream_userdriver variable during compilation, we will not be able to fix the starting address of the streaming driver module compilation, in this way, we do not know where to deploy the compiled binfile. In addition, the g_generalstream_userdriver variable cannot be kept in a relatively definite position with the binfile (which is related to the actual code size ), to solve this problem, I still have to worry about it. (If you have a better method to determine the g_generalstream_userdriver address, you can talk about it ).

The first problem is solved. We have implemented the host to load and call the streaming driver interface.

The second problem is that my initial practice was absolute positioning. I first declared a function pointer based on the prototype of the system function, and then found the absolute address of the function based on the compiled map file, make a conversion. The following code:

 
TypedefVoid(* Mf_ LCD _printf )(Char Const*Format ,...);# DefineLCD _printf (mf_ LCD _printf) 0x0805ab73)

After this step, we can directly call this system function in the stream drive interface. However, there is an obvious problem in this process, that is, once the system firmware is upgraded (requires re-compilation), these absolute addresses may change. Once there is a change, this is fatal to the streaming driver. Not only does the call fail, but it is very likely that the system will be suspended (if it is a Windows system, it will be a blue screen ).

Therefore, I used another method. Like the method that a streaming Driver provides a streaming driver interface, the system's API interface is also defined in a variable, as shown in the following code:

 Const Igeneralstream_function g_generalstream_function = { & Notice_generateevent, & LCD _printf, & Debug_printf, & Hal_time_sleep_microseconds_interruptenabled, & Cpu_gpio_disablepin, & Cpu_gpio_enableinputpin, &Cpu_gpio_enableoutputpin, & Cpu_gpio_getpinstate, & Cpu_gpio_setpinstate, & Cpu_timer_initialize, & Cpu_timer_uninitialize, & Cpu_timer_start, & Cpu_timer_stop, & Cpu_timer_getstate, & Cpu_timer_setstate ,}; 

When the host calls the streaming Driver Interface, directly transfer the g_generalstream_function address to a streaming driver. The advantage of this method is that it is not affected by the system firmware upgrade, but the disadvantage is also obvious, that is, the interface provided by the system for you to use (in fact, at this time, the first method is still valid, but it can be regarded as a hacker ).

It is also worth mentioning that, because this is a driver-level development, the driver can theoretically access any system resources, therefore, the driver must work in the pre-planned code and ram areas as much as possible to avoid impact on system stability.

The above idea is just a preliminary step. We can add a class PE header to the stream driver just like the PE file, and export the function pointer and the system API pointer to be referenced and other resources, enter the class PE Header. In this way, the system can automatically load Various Stream drivers based on the PE Header Information for upper-layer applications to call.

The following is a scenario for developing a streaming driver for MDK. I will write a special article on how to write and use a streaming driver in the future. net micro framework Dynamic Load C/C ++ code application.

Mf Introduction: http://blog.csdn.net/yefanqiu/article/details/5711770

Mf data: http://www.sky-walker.com.cn/News.asp? Id = 25

 

 

 

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.