How to fully support C++11 on RTOS

1 Overview

1.1, the characteristics of C++ language

C language has been widely used in system and application development since its birth. For example, Google's microkernel operating system fuchsia is implemented in C, and ARM's embedded operating system ARMmbed is also mainly implemented based on C. In terms of application development, C is widely used in the development of GUI, game engines, graphics engines, browser engines, databases, etc.

The wide use of C++ language benefits from the following characteristics:
(1) Support for object-oriented programming, and mechanisms such as encapsulation, inheritance, and polymorphism make programming more efficient.
(2) Compatible with C, support process-oriented programming and driver development.
(3) The standard library supports rich file and data structure operations.
(4) Excellent performance.

 

1.2 Application of C++ on Embedded RTOS

With the enhancement of MCU chip processing capabilities, the graphics display, pattern recognition, and script analysis capabilities of embedded devices continue to empower devices to expand their application boundaries. At the same time, with the continuous expansion of applications, higher requirements are put forward for embedded devices. Generally, embedded systems are developed using C language, but complex applications such as GUI and AI algorithms are developed using C. For this reason, the demand for supporting C language on RTOS has become stronger and stronger.

 

Some RTOS packaging system interfaces provide custom C classes for upper-layer applications, but because these classes do not conform to the C standard, applications developed based on these classes lack portability. On the other hand, when external open source software is used, adaptation is required. If the software is more complicated and the adaptation workload is relatively large, it is even more catastrophic. Because the custom classes are not complete, it is often difficult to meet the requirements of the upper software. need. Therefore, the most feasible method is to support the standard C++ library.

 

 

This article mainly elaborates the two key parts of supporting C++ on RTOS based on the GCC tool chain:

  • Support for C++ initialization on RTOS;
  • Adapt C++ library on RTOS;

Note: This article is based on the practice of C++11 on the Internet of Things operating system AliOS Things, and has been applied in scenarios such as smart speakers.

 

2. C++ initialization support

For the C language, only constants or constant expressions can be used to initialize global variables. For example, call function initialization is not allowed, nor is it allowed to initialize with another global variable. In other words, the value of the global variable is determined at compile time. In addition, for the global array, its length is also determined at compile time.

The compiler puts global variables without initial values ​​in the bss section, and global variables with initial values ​​in the data section (read-only data is put in the rodata section). When the RTOS starts, all the bss segments are cleared to 0, and the content of the data segment is read from the program image and written to the memory of the corresponding data segment, thus completing the initialization of all global variables.

After the introduction of C++, there is the concept of objects. At this time, the initialization in the RTOS startup process is no longer as simple as clearing memory and copying memory. The space inside the object needs to be allocated by calling new, such as the virtual function table and the internal storage space of some containers. At the same time, the constructor of the parent class needs to be called during the object initialization process. None of these can be determined at compile time.

 

The way C handles this problem is to put all the addresses of the functions that need to be called during initialization in all C source files into one table, and RTOS traverses the function table and calls each function during initialization to complete the C++ object initialization.

 

When RTOS starts, the pseudo code to initialize the C++ object is as follows:

    for (f = __ctors_start__; f < __ctors_end__; f++) {

        (*f)();

    }

 

3. Adapt the C++ library on RTOS

After realizing the initialization support for C on RTOS, download a tool chain provided by the chip manufacturer and configure the compilation options. C seems to be able to run, but there are actually many problems.

Chip manufacturers provide either a Linux-based tool chain or a bare-metal tool chain (bare-metal). Obviously, only bare-metal tool chain can be selected on RTOS. The so-called bare-metal, its meaning is no operating system platform, its thread mode is single, that is, no multi-threaded concurrency. In this mode, C multi-threading is not supported, for example, mutex, thread, condition_variable and other classes are not supported. At the same time, multi-thread mutual exclusion is not considered in the internal implementation of the C library. Therefore, the tool chain in this mode is used on RTOS, on the one hand, it has incomplete functions, on the other hand, there are hidden dangers of stability, especially on multi-core platforms, the problem of multi-thread concurrency will become serious. Therefore, in order to truly realize full support for C++11, it is necessary to adapt to RTOS.

 

3.1, the dependency of the C++ library

 

A C++ library is integrated in the GCC tool chain, and its dependencies are as follows:

The three dependent parts in the above figure are explained as follows:

  • C imports the symbols in the C library into the std namespace for upper-level applications to use. At the same time, the implementation of the C internal mechanism also relies on the C library, for example, the output stream depends on interfaces such as puts and putchar. Of course, the C library must also implement multi-threading support. This has the opportunity to open up another article to explain it, and I will not expand it here.
  • The libgcc library provides some lower-level interfaces and mechanisms. For example, the thread variable of C++ is based on the thread variable management mechanism provided by the libgcc library.
  • The C adaptation layer realizes the docking of C and RTOS, and this part is different due to the difference of the underlying OS. Therefore, the embedded tool chains provided by ARM and other chip manufacturers or compiler manufacturers are often bare-metal platforms because of the large number of RTOSs, which cannot be satisfied one by one. The multi-threaded version tool chain for a specific RTOS needs to be customized by the RTOS manufacturer.

 

3.2, adaptation

Adaptation mainly involves two parts: type and interface. For details, please refer to the ./gcc/libgcc/gthr.h file.

3.2.1. The interface description of the adaptation is as follows:

C++ internal types

Description

__gthread_t

Thread type

__gthread_key_t

Thread internal variables

__gthread_once_t

Single execution

__gthread_mutex_t

Mutually Exclusive Semaphore

__gthread_recursive_mutex_t

Supports recursive mutex semaphores

__gthread_cond_t

Condition variable

__gthread_time_t

time

 

3.2.2. The adapted interface is as follows

C++ internal interface

Description

__gthread_active_p

Return 1 indicates that multi-threading is supported, then the internal implementation of the C++ library will consider the protection of critical resources between threads

__gthread_create

Create thread

__gthread_join

Wait for the target thread to end

__gthread_detach

Thread state is set to detached

__gthread_equal

Determine whether it is the same thread

__gthread_self

Get the current thread

__gthread_yield

Give up the CPU

……

……

 

3.2.3, adaptation instructions     

Use typedef to define the C internal type as the RTOS type, and implement the above adaptation interface based on the RTOS interface to complete the adaptation of the C library. If the RTOS has completed the support for the posix interface, then the adaptation is more convenient. Examples are as follows:


    //__gthread_t类型定义

    typedef pthread_t __gthread_t;



    //__gthread_create接口实现

    static inline int

    __gthread_create (__gthread_t *__threadid,  void *(*__func) (void*), void *__args)

    {

        return pthread_create (__threadid, NULL, __func, __args);

    }

 

3.3. Configure and reprogram the C++ library

When compiling the C++ library, it needs to be configured to enable multi-threading mode. The main configuration items are as follows:
--enable-threads=posix

In fact, enabling this option only triggers the configuration script to check whether it supports multi-threading. If it is determined that the system does not support multi-threading during the execution of the configuration script, the final compiled library is still single-threaded. For example, the configuration script judges whether the __GTHREADS_CXX0X macro is defined. If the macro is not defined, the multithreading will fail to be enabled.

After completing the adaptation and configuration, reprogram the tool chain to generate a multi-threaded version of the C library. After the compilation is complete, you can check the cconfig.h file to confirm the enabled C++ features. Take the _GLIBCXX_USE_SCHED_YIELD macro as an example. If the macro is not generated, then the thread class yield() function is implemented as an empty function,

 

4. Postscript

Thanks to the good encapsulation mechanism of C++, code written in C++ has a much lower bug rate than code written in C. But the other side of the coin is that the difficulty of debugging has increased.

Even if the compiler optimization is turned on, the correspondence between a line of C language statement and assembly is relatively clear. However, due to its complex mechanism, a simple assignment statement in C++ often corresponds to a dozen or even dozens of assemblies. This requires the maintenance and testing capabilities of RTOS to provide efficient debugging support.

 

Developer technical support

If you need more technical support, you can join the DingTalk developer group, or follow the WeChat public account

For more technology and solution introduction, please visit the Aliyun AIoT homepage https://iot.aliyun.com/

Guess you like

Origin blog.csdn.net/HaaSTech/article/details/115008262