Unveiling the Internal Mechanisms of RT-Thread: Dive into the Operating System Kernel

RT-Thread IoT OS
8 min readMar 18, 2025

--

This article is reproduced from Zhu’s Tech Power Hub.

1. Overview of RT-Thread

RT-Thread is a remarkable open-source embedded real-time operating system (RTOS) with significant advantages. It not only boasts a lightweight design and strong real-time capabilities but also enjoys robust support from its expansive open-source community and has a wide range of application scenarios.

In terms of being lightweight, RT-Thread is well-suited for resource-constrained embedded environments. Through its efficient kernel design and resource management, it conserves valuable system resources for devices. Its compact kernel can operate in extremely limited storage space, making it a reliable OS choice for small-scale devices.

Real-time performance is one of the core strengths of RT-Thread. With rapid task response capabilities and precise timing control, it meets the demands of applications sensitive to timing, such as those in industrial control and aerospace sectors.

The open-source nature of RT-Thread has fueled its rapid development and widespread adoption. Numerous developers have contributed to its codebase, continuously enhancing its features and optimizing performance.

In the embedded systems domain, RT-Thread has found extensive applications. From controlling smart appliances in smart homes to monitoring production processes in industrial automation and powering in-vehicle systems in automotive electronics, its presence is notable. Its powerful features and adaptability enable various embedded devices to operate stably and efficiently.

In summary, RT-Thread plays a crucial role in the embedded systems landscape, offering developers a reliable and efficient operating system solution through its open-source characteristics, lightweight design, and real-time performance.

2.RT-Thread Startup Process

Upon powering up the system, the execution begins with the startup file. This startup file typically performs essential hardware setup tasks such as initializing the clock, configuring the interrupt vector table, and initializing the stack.

Following this, the program jumps to the entry function of RT-Thread, `rtthread_startup`. Within this function, a series of important initialization tasks are carried out sequentially.

The first step is hardware initialization, which includes configuring the system clock and initializing relevant peripherals. This lays the necessary hardware groundwork for the subsequent operation of the system.

Next, the system kernel objects are created, including timers and the scheduler. The creation of these kernel objects provides support for task scheduling and time management within the system.

Then, the `main` thread is created, along with the initialization of its stack. The `main` thread typically handles the main logic of user applications.

In the `rtthread_startup` function, the initialization of timers and the scheduler is also performed. Timer initialization ensures that the system can execute precise timing operations, while scheduler initialization establishes the foundation for efficient task allocation and switching.

Once these initialization tasks are completed, the system is ready and awaits the scheduler to start, allowing for normal operation and task scheduling to commence.

Overall, the startup process of RT-Thread is meticulous and orderly, systematically completing each initialization step to ensure stable operation and efficient task management for the system.

3.Memory Distribution of the Program

Code Segment: The code segment stores the executable portion of the program. Its size is determined at compile time, and the contents remain unchanged during runtime. When the program is compiled, the code segment occupies a certain amount of Flash memory, which the CPU reads and executes at runtime.

RO-data Segment: The RO-data segment is used to store constants defined in the program, such as string literals. These data are set at compile time and cannot be modified during runtime, residing in Flash. The RO-data segment occupies Flash memory during compilation.

RW-data Segment: The RW-data segment contains global variables that are initialized to non-zero values. While it takes up some Flash memory during compilation, the data within the RW-data segment needs to be read and written, so it is transferred from Flash to RAM during runtime.

ZI-data Segment: The ZI-data segment holds uninitialized or zero-initialized global variables. Unlike the others, the ZI-data segment does not occupy Flash space at compile time; instead, it allocates space in RAM based on the addresses and sizes provided by the compiler during runtime, initializing its contents to zero.

In summary, at compile time, the RO Size includes the Code and RO-data segments, representing the Flash memory occupied by the program. The RW Size consists of the RW-data and ZI-data segments, indicating the amount of RAM used during runtime. The ROM Size encompasses the Code, RO-data, and RW-data segments, reflecting the Flash memory required for programming. During program execution, the CPU reads the contents of the Code and RO-data segments from Flash and accesses the RW-data and ZI-data segments from RAM.

4.Automatic Initialization Mechanism

The automatic initialization mechanism of RT-Thread is cleverly implemented using macro definitions. Specific macros are used to declare initialization functions at the point of function definition, which automatically get executed during the system startup without the need for manual calls.

INIT_BOARD_EXPORT is primarily used for very early initialization tasks, such as hardware initialization related to the chip, while the scheduler has not yet started. It is suitable for crucial hardware initialization operations that need to be completed at the very early stages of system startup.

INIT_PREV_EXPORT is intended for purely software-related initialization, typically involving functions that have minimal dependencies, such as basic software configurations or early initialization of software modules.

INIT_DEVICE_EXPORT is aimed at the initialization of peripheral drivers, like network interface devices. It is used when peripherals need initialization to ensure the system can operate normally afterward.

INIT_COMPONENT_EXPORT focuses on the initialization of components, such as initializing file systems or LWIP (Lightweight IP).

INIT_ENV_EXPORT is used for initializing the system environment, including actions like mounting the file system.

INIT_APP_EXPORT is for application initialization, such as setting up GUI applications.

By using these various types of automatic initialization interfaces, developers can place functions in the appropriate initialization stage according to their specific needs, ensuring the system efficiently and orderly completes all initialization tasks during startup. This approach enhances both development efficiency and system stability.

5.Kernel Object Model

The RT-Thread kernel object model is diverse and includes various objects such as threads, semaphores, mailboxes, message queues, and memory pools.

Threads: Threads are the fundamental units of scheduling in RT-Thread, representing the context and priority of task execution. Each thread control block stores critical information about a thread, including its priority, state, and stack address.

Semaphores: Semaphores are employed to solve synchronization and mutual exclusion issues between threads. The count value of the semaphore controls access to resources; when the count reaches zero, any thread attempting to access the resource will be blocked.

Mailboxes: Mailboxes facilitate message passing between threads and can store a certain amount of message data.

Message Queues: Message queues can hold multiple messages and support asynchronous communication between different threads.

Memory Pools: Memory pools are used to efficiently manage memory allocation and release, enhancing the efficiency of memory usage.

The kernel object management framework utilizes linked lists to manage various types of objects. Each kernel object type has its corresponding linked list, and objects are connected through linked list nodes — for example, thread objects are managed via a thread linked list.

The inheritance and derivation relationships of these objects provide significant advantages. On one hand, they enhance the system’s reusability and scalability; new object types can be created with minimal extensions based on common attributes, simplifying the development process. On the other hand, they offer a unified manner for object operations, streamlining the operation processes of specific objects and improving system reliability and stability. For instance, the thread control block inherits the structure of a generic object while adding thread-specific attributes, allowing for more precise and efficient thread management.

6.Thread Management

6.1 Basic Concepts of Multithreading and Implementation in RT-Thread

In operating systems, multithreading breaks a large task into multiple independently executable smaller tasks, thereby improving the system’s concurrency capabilities. In RT-Thread, threads are managed through thread control blocks, with each thread having its own execution environment and priority. Threads can cooperate through shared resources and communication mechanisms.

6.2 Attributes Related to Threads

Thread Stack: Each thread in RT-Thread has its own stack to store local variables and context information during runtime. When switching threads, the context is saved to the stack and restored from the stack when the thread resumes execution.

Thread States: Threads exist in five states:

Initial: The thread has been created but is not yet running.

Ready: The thread is prepared and waiting to be scheduled for execution.

Running: The thread is currently executing and occupying the CPU.

Suspended: The thread is temporarily not participating in scheduling, typically due to resource unavailability or intentional delay.

Closed: Indicates that the thread has completed its execution.

Thread Priority: RT-Thread supports up to 256 priority levels, with lower numeric values indicating higher priority (0 being the highest). Thread priorities can be set according to actual needs to determine the scheduling order of threads.

Time Slices: Time slices apply only to ready threads of the same priority level. They define how long each thread of the same priority can run, influencing system responsiveness and task switching frequency.

6.3 System Threads

Idle Thread: The idle thread has the lowest priority and is always in the ready state. When no other threads are ready, the scheduler will dispatch the idle thread, which typically runs in an infinite loop executing background tasks, such as resource recovery and power management.

Main Thread: Created during system startup, the entry function is `main_thread_entry`. User application entry starts from here, allowing users to add their application initialization code in the `main` function.

6.4 APIs Related to Thread Scheduling

Start: The `rt_thread_startup` function queues the created or initialized thread into the corresponding priority ready queue, waiting for it to be scheduled for execution.

Get Current: The `rt_thread_self` function retrieves the handle of the currently executing thread.

Yield Resources: The `rt_thread_yield` function allows the current thread to yield CPU resources, enabling other threads of the same priority to execute.

Sleep: Functions like `rt_thread_sleep`, `rt_thread_delay`, and `rt_thread_mdelay` can suspend the current thread for a specified time, bringing it back to the ready state once the time period ends.

Suspend and Resume: The `rt_thread_suspend` function suspends a thread, while `rt_thread_resume` brings a suspended thread back into action.

Control: The `rt_thread_control` function allows for dynamic changes to the thread’s priority and other attributes.

7.Clock Management

7.1 Concept and Role of OS Tick

OS Tick is the smallest time unit in the RT-Thread operating system, functioning like the system’s heartbeat. It provide a baseline for managing various time-related events within the system. In RT-Thread, OS Tick is widely used in scenarios such as thread delays, time-slicing, and timer timeouts.

In the context of thread delays, OS Tick allows for precise control over the duration a thread is paused, ensuring that threads execute at predetermined time intervals.

For time-slicing scheduling, OS Tick determines the length of time each thread occupies the CPU, facilitating fair round-robin execution among threads and enhancing the system’s concurrency capabilities.

In terms of timer timeouts, OS Tick is crucial. When the time set for a timer reaches the corresponding number of OS Tick, a timeout operation is triggered, executing the appropriate callback function.

7.2 Implementation Principle of OS Tick

The implementation of OS Tick in RT-Thread relies on hardware timers configured to operate in interrupt-triggered mode. Typically, a hardware timer, such as the SYSTICK timer used in Cortex-M chips, is utilized for this purpose.

When an interrupt occurs, a series of counting and processing functions are invoked. The interrupt service routine (ISR) handles critical operations related to OS Tick, such as incrementing the tick count and managing any associated events.

--

--

RT-Thread IoT OS
RT-Thread IoT OS

Written by RT-Thread IoT OS

An Open-Source Community-Powered Real-Time Operating System (RTOS) Project! Let’s develop, DIY, create, share, and explore this new IoT World together!

No responses yet