当前位置:网站首页>RT thread kernel quick start, kernel implementation and application development learning with notes

RT thread kernel quick start, kernel implementation and application development learning with notes

2022-07-05 08:50:00 Chaser Bridge

Preface

Official documents for beginners :

Keil Simulator STM32F103 (rt-thread.org)https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-standard/tutorial/quick-start/stm32f103-simulator/stm32f103-simulator official API Reference manual :

RT-Thread API Reference manual : event_sample.chttps://www.rt-thread.org/document/api/event_sample_8c-example.html#a10         The following contents are sorted out at any time with learning , Some come from wildfires 《RT-Thread Kernel Implementation and application development 》 Learning notes of , Some things from the official website , Write down what you think is difficult to remember and important .

        You can browse and know , As for you who want to know more, I hope you can read the relevant documents by yourself .

Quick start  

You can go to the official documentation

First of all, will KEIL download , There are relevant routines on the official website

Project description

 

  Debug command

Open the debugging public and click Run (F5) Code , Open the serial port UART#1, Click on Tab Key or help+ enter , Check the commands supported by the system .

  System startup steps

          With MDK-ARM For example ,MDK-ARM The user program entry for is main() function , be located main.c In file . After the system starts, start from the assembly code startup_stm32f103xe.s Began to run , And then jump to C Code , Conduct RT-Thread System function initialization , Finally, enter the user program entry main().

  If used ARM The kernel redefines when it starts , Finally jumped to rtthread_startup(); yes RT-Thread Specified uniform start entry .  The initialization of the startup program function is shown in the following figure :

  The startup code is divided into four parts :

User entry code

         In order to enter main Before the program , Complete system function initialization , have access to  $sub$$  and  $super$$  The function identifier calls another routine before entering the main program. , This allows users to ignore main() Previous system initialization .

Kernel Foundation

Components of the kernel 、 How the system starts up 、 Memory distribution and kernel configuration method .

The implementation of real-time kernel includes : Object management 、 Thread management and scheduler 、 Inter thread communication management 、 Clock management and memory management, etc , The minimum resource usage of the kernel is 3KB ROM,1.2KB RAM.

Thread scheduling

         Thread is RT-Thread The smallest scheduling unit in the operating system , Thread scheduling algorithm is a priority based full preemptive multithreading scheduling algorithm , That is, in addition to Interrupt handling function 、 The code of the locking part of the scheduler and the code of prohibiting interruption It's beyond what can't be preempted , Other parts of the system can be preempted , Including the thread scheduler itself .

Clock management

        RT-Thread Clock management is based on clock beat , The beat of the clock ( Tick always ) yes RT-Thread The smallest unit of clock in an operating system .RT-Thread The timer provides two types of timer mechanisms : The first category is Single trigger timer , This kind of timer will only trigger one timer event after starting , Then the timer stops automatically . The second type is Cycle triggered timer , This kind of timer will trigger timer events periodically , Until the user manually stops the timer, it will continue to execute forever .

in addition , According to the context in which the timeout function is executed ,RT-Thread The timer can be set to HARD_TIMER Mode or SOFT_TIMER Pattern .

Usually use timer timing callback function ( Timeout function ), Complete the scheduled service . Users choose the appropriate type of timer according to their real-time requirements for timing processing .

Synchronization between threads

        RT-Thread Use semaphores 、 Mutex and event set achieve synchronization between threads . Thread through the semaphore 、 The acquisition and release of mutex are synchronized ; Mutex solves the common priority reversal problem in real-time system by priority inheritance , Semaphores can lead to thread blocking, that is, when low priority holds semaphores , High priority cannot get semaphore .

Inter thread communication

         RT-Thread Support communication mechanisms such as mailbox and message queue . The length of a message in the mailbox is fixed as 4 Byte size ; Message queues can receive messages of variable length , And cache messages in your own memory space . Mailbox efficiency is more efficient than message queuing . The sending action of mailbox and message queue can be safely used in interrupt service routine . The communication mechanism supports threads to wait according to priority or obtain information in a first in first out manner .

memory management

        RT-Thread Support static memory pool management and dynamic memory heap management . When the static memory pool has available memory , The time allocated by the system to memory blocks will be constant ; When the static memory pool is empty , The system suspends or blocks the thread applying for the memory block ( That is, if the thread does not get the memory block after waiting for a period of time, it will give up the application and return , Or return immediately . The waiting time depends on the waiting time parameter set when applying for a memory block ), When other threads release memory blocks to the memory pool , If there is a thread of pending memory block to be allocated , The system will wake up this thread .

The dynamic memory heap management module is used when the system resources are different , Respectively provided Memory management algorithm for small memory systems And For large memory systems SLAB Memory management algorithm .

There is also a dynamic memory heap management called memheap, It is applicable to the discontinuous memory heap with multiple addresses in the system . Use memheap Can be Multiple memory heaps “ Paste ” together , Let the user operate like operating a memory heap .

I/O Equipment management

        RT-Thread take PIN、I2C、SPI、USB、UART As peripheral equipment , It is completed through device registration . The device management subsystem accessed by name is realized , According to the unified API Interface to access hardware devices . On the device driver interface , According to the characteristics of embedded system , Corresponding events can be attached to different devices . When a device event is triggered , The driver notifies the upper application .

Program memory distribution

commonly MCU The storage space included is : Intraslice Flash( Hard disk ) And on-chip RAM( Memory ). The compiler will classify a program into several parts , Store separately in MCU Different storage areas .

Keil After the compilation of the project , The corresponding program prompts to occupy space

  1. Code: Code segment , Store the code part of the program ;
  2. RO-data: Read only data segment , Store constants defined in the program ;
  3. RW-data: Read and write data segments , Store initialization to non 0 Global variable of value ;
  4. ZI-data:0 Data segment , Store uninitialized global variables and initialize to 0 The variable of ;

After compilation, the project will generate a .map file , It explains the size and address occupied by each function , The relationship between the last few lines of the document and the scene .

  1. RO Size Contains Code And RO-data, Indicates that the program occupies Flash The size of the space ;
  2. RW Size Contains RW-data And ZI-data, Represents the time occupied by the runtime RAM Size ;
  3. ROM Size Contains Code、RO-data as well as RW-data, Represents the time occupied by the burning program Flash The size of the space ;

STM32 After power on and start, the default is from Flash start-up , After startup, it will RW In paragraph RW-data( Initialized global variables ) Carry to RAM in , But not moving RO paragraph , namely CPU Execution code from Flash Read from , In addition, according to the compiler ZI Address and size allocation ZI paragraph , And put this RAM Area clear .

Application of dynamic memory :msg_ptr The pointer points to 128 The byte memory space is located in the dynamic memory heap space .

  Some global variables are stored in RW Paragraph and ZI In the paragraph ,RW The segment stores global variables with initial values ( Global variables in the form of constants are placed in RO In the paragraph , Is read-only ),ZI The system uninitialized global variable stored in the segment .

Automatic initialization mechanism

The explicit initialization mechanism does not need to be called , It only needs to be declared in the way of macro definition at the function definition , Will be executed during system startup .

Kernel object model

Static and dynamic objects  

Static kernel objects are usually placed in RW Paragraph and ZI In the paragraph , Initialize in the program after the system starts ;

Dynamic kernel objects are created from the memory heap , Then do initialization manually , Finally, you need to release .

Static objects take up RAM Space , Does not depend on the memory heap manager , Memory allocation time determination . Dynamic objects depend on the memory heap manager , Runtime request RAM Space , When an object is deleted , The amount of RAM Space is released . Both ways have their own advantages and disadvantages , You can choose the specific use mode according to the actual environmental needs .

Kernel object management architecture

Static objects take up RAM Space , Does not depend on the memory heap manager , Memory allocation time determination . Dynamic objects depend on the memory heap manager , Runtime request RAM Space , When an object is deleted , The amount of RAM Space is released . Both ways have their own advantages and disadvantages , You can choose the specific use mode according to the actual environmental needs .

  Object control block

struct rt_object
{
     /*  Kernel object name      */
     char      name[RT_NAME_MAX];
     /*  Kernel object type      */
     rt_uint8_t  type;
     /*  Parameters of kernel object    */
     rt_uint8_t  flag;
     /*  Kernel object management linked list  */
     rt_list_t   list;
};
struct rt_object_information
{
     /*  object type  */
     enum rt_object_class_type type;
     /*  Object linked list  */
     rt_list_t object_list;
     /*  Object size  */
     rt_size_t object_size;
};

Traverse kernel objects

rt_thread_t thread = RT_NULL;
struct rt_list_node *node = RT_NULL;
struct rt_object_information *information = RT_NULL;

information = rt_object_get_information(RT_Object_Class_Thread);

rt_list_for_each(node, &(information->object_list))
{
    thread = (rt_thread_t)rt_list_entry(node, struct rt_object, list);
    /*  For example, print all thread Name  */
    rt_kprintf("name:%s\n", thread->name);
}
rt_mutex_t mutex = RT_NULL;
struct rt_list_node *node = RT_NULL;
struct rt_object_information *information = RT_NULL;

information = rt_object_get_information(RT_Object_Class_Mutex);

rt_list_for_each(node, &(information->object_list))
{
    mutex = (rt_mutex_t)rt_list_entry(node, struct rt_object, list);
    /*  For example, print all mutex Name  */
    rt_kprintf("name:%s\n", mutex->parent.parent.name);
}

Kernel configuration and tailoring

Configuration is mainly achieved by modifying rtconfig.h file To carry out , Users can open / Close the macro definition in the file to conditionally compile the code , Finally achieve the purpose of system configuration and tailoring

notes : in application , System profile rtconfig.h It is automatically generated by the configuration tool , No manual changes are required .

 

The first 8 Chapter Thread definition and thread switching

Define thread stack :

  • rt_uint8_t

         These redefined data types are placed in rtdef.h(rtdef.h The first use needs to be in include Create a new folder and add it to the project rtt/source This group of files ) This header file .
  • ALIGN 

         Is a macro with parameters , Also in the rtdef.h In the definition of
  •  RT_ALIGN_SIZE

It's a rtconfifig.hrtconfifig.h The first use needs to be in User Create a new folder and add it to the project user
This group of files ) Macro defined in

Please refer to the real-time manual for the composition of threads

RT-Thread API Reference manual : event_sample.chttps://www.rt-thread.org/document/api/event_sample_8c-example.html#a10

        
  •   follow RT-Thread Function naming rules in , In lowercase rt start , Indicates that this is an external function , Can be called by the user , With _rt The function at the beginning represents the internal function , Only by RT-Thread For internal use . Followed by the file name , Indicates which file the function is placed in , Finally, the function name .
  • thread A thread is a pointer control block .
  • entry Is the thread function name , Represents the entry of the thread .
  • parameter Is a thread parameter , Used to pass thread parameters .
  • stack_start Used to point to the starting address of the thread stack .
  • stack_size Indicates the size of the thread stack , The unit is byte .

Linked list

  These functions are all in rtservice.h To realize ,rtservice.h For the first time, you need to use it on your own rtthread/3.0.3/include New under folder , Then add to the project rtt/source In the group .

  • Initializing list nodes

  •   Insert a node after the header of the bidirectional linked list

  •   Insert a node in front of the header of the bidirectional linked list

  •   Delete a node from the two-way linked list

Thread stack initialization :rt_hw_stack_init() function

/* Get stack top pointer rt_hw_stack_init At call time , Pass to stack_addr Yes. ( Top pointer of stack )*
stk = stack_addr + sizeof(rt_uint32_t);

 

stk = (rt_uint8_t *)RT_ALIGN_DOWN((rt_uint32_t)stk, 8);
Give Way stk This pointer goes down 8 Byte alignment , Make sure stk yes 8 Byte aligned address . stay Cortex-M3Cortex-M4 or Cortex-M7) In the single chip microcomputer of the kernel , Because the bus width is 32 Bit , Usually as long as the stack remains 4 Byte alignment is ok , But why do you have to 8 byte ? Are there any operations 64 Bit ? It does , That's floating point arithmetic , So we need to 8 Byte alignment ( But at present, we have not involved in floating-point operation , Just for the sake of subsequent compatible floating-point operation ). If the pointer at the top of the stack is 8 Byte Alignment , Going down 8 When aligning bytes , The pointer will not move , If not 8 Byte Alignment , Doing down 8 When aligning bytes , A few bytes will be left empty , Can't use , For example, when stk yes 33, Obviously not divisible 8, Go down 8 Byte alignment is 32, Then one byte will be left unused .
The first time a thread runs , Load into CPU The environment parameters of the register should be initialized in advance . From the top of the stack , The initialization sequence is fixed , First, it is automatically saved when an exception occurs 8 A register , namely xPSRR15R14R12R3R2R1 and R0. among xPSR Bit of register 24 Must be 1,R15 PC The pointer must store the entry address of the thread ,R0 Must be a thread parameter , The rest R14、R12、R3、R2 and R1 We initialize to 0.

 

Insert the thread into the bidirectional ready list        

          After the thread is created , We need to Add the thread to the ready list , Indicates that the thread is ready , The system can schedule at any time . The ready list is scheduler.c In the definition of (scheduler.c The first use needs to be in rtthread3.0.3src New under the directory , Then add to the project rtt/source In the group ).

  • Implement the scheduler

         Scheduler is the core of operating system , Its main function is to realize thread switching , That is, find the thread with the highest priority from the ready list , Then execute the thread . In terms of code , The scheduler is nothing more than a few global variables and some functions that can realize thread switching , All in scheduler.c Implementation in file .

Define a local variable , use C Language keywords register modification , Prevent optimization by compiler . We put scheduler initialization after hardware initialization , Before thread creation

The scheduler is started by the function rt_system_scheduler_start() To complete

System scheduling

System scheduling is to find the highest priority ready thread in the ready list , Then execute the thread . But at present, we don't Support priority , Only two threads can switch in turn , System scheduling function rt_schedule.

main function

Thread creation , Implementation of the ready list , The implementation of the scheduler has been finished , Now let's put all the test code into main.c Inside

The first 9 Chapter Protection of critical section

         The critical section is summarized in one sentence, that is, when a section is executed Code snippets that cannot be interrupted . stay RT-Thread Inside , The most common occurrence of this critical segment is the operation of global variables .
         So when will the critical section be interrupted ? One is system scheduling , There is also an external interrupt . stay RT-Thread, System scheduling , Finally, it also produces PendSV interrupt , stay PendSV Handler It realizes thread switching , So it can be reduced to interruption . In this case ,RT-Thread The protection of critical section is handled simply , Just turn off all interrupts ,NMIFAULT And hard FAULT With the exception of .

The first 10 Chapter   Implementation of object container

stay RT-Thread in , All data structures are called objects .

stay RT-Thread in , Each object has a corresponding structure , This structure is called the control block of the object .

stay rtt in , Whenever a user creates an object , Threads such as , This object will be placed in a place called container . 

What is a container , From the code point of view , A container is an array , Is a global variable , The data type is struct
rt_object_information, stay object.c In the definition of

 

C language knowledge : If the member value of the enumeration type is not specified , Then the latter value is added to the previous member value 1.

原网站

版权声明
本文为[Chaser Bridge]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/186/202207050840533354.html