3360 views|2 replies

530

Posts

4

Resources
The OP
 

【RT-Thread Reading Notes】4. RT-Thread Study Chapter 6 Reading Notes (I) [Copy link]

 This post was last edited by Media Students on 2019-4-27 21:54
【RT-Thread Reading Notes】4. RT-Thread Learning Chapter 6 Reading Notes
---The definition of threads and the implementation of thread switching (I)
This sharing corresponds to the contents of 6.1-6.3 in Chapter 6 of "RT-thread Kernel Implementation and Application Development Practical Guide".
Threads are the foundation of RTOS and are very important. Thread switching is implemented using assembly code, which should be to write arm instruction code directly in assembly to implement thread switching. The advantage of doing so is that the switching speed should be faster than that of C.
Why use assembly to implement thread switching?
It may be that assembly is closer to the bottom layer, and the speed may be faster than that of C, because in RTOS, thread switching is a very frequent operation, and thread switching will use stacks or heaps to store or read context.
1. Definition of thread:
In a bare metal system, the system has only one thread, that is, the large loop in the main function; in an RTOS, there are many such large loops, and each large loop is referred to as a thread. County switching is completed through task schedulers, etc. 2. Create threads: In a bare metal system, there will be global variables, sub-function calls, and interrupts. When the system is running, we don't need to pay much attention to where these things are stored. But in RTOS, there are many threads. We must figure out where these things are stored so that we can call them and ensure the correct operation of RTOS. Usually these parameters will be stored in the stack, which is generally a space in RAM. In RTOS, threads are independent of each other and do not interfere with each other. Therefore, we need to allocate independent stack space for each thread. Therefore, we will find out why RTOS takes up a larger RAM space than bare metal system. Define thread stack: rt_uint8_t rt_flag1_thread_stack[512]; rt_uint8_t rt_flag2_thread_stack[512]; In RT-Thread, all places involving data types will be in rtdef.h中重新定义:
  1. /* RT-Thread basic data type definitions */
  2. typedef signed   char                   rt_int8_t;      /**<  8bit integer type */
  3. typedef signed   short                  rt_int16_t;     /**< 16bit integer type */
  4. typedef signed   long                   rt_int32_t;     /**< 32bit integer type */
  5. typedef unsigned char                   rt_uint8_t;     /**<  8bit unsigned integer type */
  6. typedef unsigned short                  rt_uint16_t;    /**< 16bit unsigned integer type */
  7. typedef unsigned long                   rt_uint32_t;    /**< 32bit unsigned integer type */
  8. typedef int                             rt_bool_t;      /**< boolean type */
  9. /* 32bit CPU */
  10. typedef long                            rt_base_t;      /**< Nbit CPU related date type */
  11. typedef unsigned long                   rt_ubase_t;     /**< Nbit unsigned CPU related data type */
  12. typedef rt_base_t                       rt_err_t;       /**< Type for error number */
  13. typedef rt_uint32_t                     rt_time_t;      /**< Type for time stamp */
  14. typedef rt_uint32_t                     rt_tick_t;      /**< Type for tick count */
  15. typedef rt_base_t                       rt_flag_t;      /**< Type for flags */
  16. typedef rt_ubase_t                      rt_size_t;      /**< Type for size number */
  17. typedef rt_ubase_t                      rt_dev_t;       /**< Type for device */
  18. typedef rt_base_t                       rt_off_t;       /**< Type for offset */
  19. /* boolean type definitions */
  20. #define RT_TRUE                         1               /**< boolean true  */
  21. #define RT_FALSE                        0               /**< boolean fails */
复制代码

3.定义线程函数:每个线程都是一个无限循环且不能返回的函数,其实就是以前裸机系统的main函数。

4.定义线程控制块:线程控制块是保存每个线程运行所需的所有信息的地方,例如线程的栈指针,线程名称,线程的各种参数等。系统可以通过线程控制块,实现对线程的调度。
      rt-thread中声明如下:
  1. /*
  2. *************************************************************************
  3. *                               线程结构体
  4. *************************************************************************
  5. */
  6. struct rt_thread
  7. {
  8.         void        *sp;                  /* 线程栈指针 */
  9.         void        *entry;                  /* 线程入口地址 */
  10.         void        *parameter;              /* 线程形参 */        
  11.         void        *stack_addr;      /* 线程起始地址 */
  12.         rt_uint32_t stack_size;       /* 线程栈大小,单位为字节 */
  13.         
  14.         rt_list_t   tlist;            /* 线程链表节点 */
  15. };
  16. typedef struct rt_thread *rt_thread_t;
复制代码

我们看到,这个结构体中,定义中使用了指针,其实指针这个东西真的很简单,就是一个tag,因为实际的物理地址比较长,一般是0xXXXXXXXXX, 为了方便,我们定义了一个指针,这个指针就代表这个实际的地址,而指针也是一个变量,它也会占用内存,因此会有指针的指针。建议好好理解一下指针, 因为有些老师在教书的时候,给大家灌输一种指针很难学,指针容易出错的错误理念,造成我们谈指色变,反正我是深受其害。希望有些老师在教书的时候,还是要客观的讲述一些东西,指针很重要,而不是指针很难用。这里多说了一点东西,有些地方可能理解有误,大家还是以书本讲述为准。
5.线程创建函数的实现:
      首先,是初始化函数:
  1. #includeDefine a thread control block: The thread control block is where all the information required for each thread to run is stored, such as the thread's stack pointer, thread name, various parameters of the thread, etc. The system can schedule threads through the thread control block. The declaration in rt-thread is as follows: [code]/* ***************************************************************************** * Thread structure******************************************************************** */ struct rt_thread { void *sp; /* Thread stack pointer*/ void *entry; /* Thread entry address*/ void *parameter; /* Thread parameter*/ void *stack_addr; /* Thread starting address*/ rt_uint32_t stack_size; /* Thread stack size, in bytes*/ rt_list_t tlist; /* Thread linked list node*/ }; typedef struct rt_thread *rt_thread_t;
复制代码
We can see that in this structure, a pointer is used in the definition. In fact, a pointer is really simple. It is just a tag. Because the actual physical address is relatively long, it is usually 0xXXXXXXXXX, For convenience, we define a pointer, which represents the actual address. A pointer is also a variable, which also occupies memory, so there will be a pointer to a pointer. It is recommended to understand pointers well, because some teachers, when teaching, instill in everyone the wrong idea that pointers are difficult to learn and easy to make mistakes, which makes us talk about pointers in a dreadful way. Anyway, I have suffered greatly from this. I hope that some teachers will still explain some things objectively when teaching, that pointers are important, not that pointers are difficult to use. I have said a little more here, and some places may be misunderstood. Please refer to the book for the description. 5. Implementation of thread creation function: First, the initialization function:
  1. #includeDefine a thread control block: The thread control block is where all the information required for each thread to run is stored, such as the thread's stack pointer, thread name, various parameters of the thread, etc. The system can schedule threads through the thread control block. The declaration in rt-thread is as follows: [code]/* ***************************************************************************** * Thread structure******************************************************************** */ struct rt_thread { void *sp; /* Thread stack pointer*/ void *entry; /* Thread entry address*/ void *parameter; /* Thread parameter*/ void *stack_addr; /* Thread starting address*/ rt_uint32_t stack_size; /* Thread stack size, in bytes*/ rt_list_t tlist; /* Thread linked list node*/ }; typedef struct rt_thread *rt_thread_t;
复制代码
We can see that in this structure, a pointer is used in the definition. In fact, a pointer is really simple. It is just a tag. Because the actual physical address is relatively long, it is usually 0xXXXXXXXXX, For convenience, we define a pointer, which represents the actual address. A pointer is also a variable, which also occupies memory, so there will be a pointer to a pointer. It is recommended to understand pointers well, because some teachers, when teaching, instill in everyone the wrong idea that pointers are difficult to learn and easy to make mistakes, which makes us talk about pointers in a dreadful way. Anyway, I have suffered greatly from this. I hope that some teachers will still explain some things objectively when teaching, that pointers are important, not that pointers are difficult to use. I have said a little more here, and some places may be misunderstood. Please refer to the book for the description. 5. Implementation of thread creation function: First, the initialization function:
  1. #include<rtthread.h>
  2. #include <rthw.h>
  3. rt_err_t rt_thread_init(struct rt_thread *thread, void (*entry)(void *parameter), void *parameter, void *stack_start, rt_uint32_t stack_size) { rt_list_init(&amp;(thread-&gt;tlist)); thread-&gt;entry = (void *)entry; thread-&gt;parameter = parameter; thread-&gt;stack_addr = stack_start; thread-&gt;stack_size = stack_size; /* Initialize the thread stack and return the thread stack pointer*/ thread-&gt;sp = (void *)rt_hw_stack_init( thread-&gt;entry, thread-&gt;parameter, (void *)((char *)thread-&gt;stack_addr + thread-&gt;stack_size - 4) ); return RT_EOK; }
复制代码
5.1 Implement linked list related functions rt_list_init(&(thread->tlist)); Initialize the thread linked list node and hang the thread control block in the linked list.
  1. /* ************************************************************************* * Doubly linked list structure******************************************************************** */ struct rt_list_node { struct rt_list_node *next; /* points to the next node*/ struct rt_list_node *prev; /* points to the previous node*/ }; typedef struct rt_list_node rt_list_t;
复制代码
Initialize the linked list node: point the next and pre node pointers in the node to the node itself. Insertion and deletion of a doubly linked list are very important knowledge for implementing task control. It is recommended that you carefully master and understand these contents. These knowledge data structures will be introduced in detail, and there are also many introductions in this book, so I will not go into details here. 5.2 rt_hw_stack_init() function
  1. #include<rtthread.h>
  2. /* ********************************************************************** * Data type******************************************************************** */ struct exception_stack_frame { /* Registers automatically saved when an exception occurs*/ rt_uint32_t r0; rt_uint32_t r1; rt_uint32_t r2; rt_uint32_t r3; rt_uint32_t r12; rt_uint32_t lr; rt_uint32_t pc; rt_uint32_t psr; }; struct stack_frame { /* r4 ~ r11 register Registers that need to be manually saved when an exception occurs*/ rt_uint32_t r4; rt_uint32_t r5; rt_uint32_t r6; rt_uint32_t r7; rt_uint32_t r8; rt_uint32_t r9; rt_uint32_t r10; rt_uint32_t r11; struct exception_stack_frame exception_stack_frame; }; /* ************************************************************************* * Global variables ************************************************************************** */ /* Pointer to the sp of the stack of the previous thread*/ rt_uint32_t rt_interrupt_from_thread; /* Pointer to the sp of the stack of the next thread to be run*/ rt_uint32_t rt_interrupt_to_thread; /* PendSV interrupt service function execution flag*/ rt_uint32_t rt_thread_switch_interrupt_flag; /* ****************************************************************************** * Function implementation ****************************************************************************** */ /* Thread stack initialization*/ rt_uint8_t *rt_hw_stack_init(void *tentry, void *parameter, rt_uint8_t *stack_addr) { struct stack_frame *stack_frame; rt_uint8_t *stk; unsigned long i; /* Get the stack top pointer rt_hw_stack_init When calling, what is passed to stack_addr is (stack top pointer)*/ stk = stack_addr + sizeof(rt_uint32_t); /* Align the stk pointer down 8 bytes*/ stk = (rt_uint8_t *)RT_ALIGN_DOWN((rt_uint32_t)stk, 8); /* The stk pointer continues to move down by sizeof(struct stack_frame) offsets*/ stk -= sizeof(struct stack_frame); /* Force the stk pointer to be converted to the stack_frame type and store it in the stack_frame */ stack_frame = (struct stack_frame *)stk; /* Using stack_frame as the starting address, initialize sizeof(struct stack_frame) memory in the stack space to 0xdeadbeef */ for (i = 0; i &lt; sizeof(struct stack_frame) / sizeof(rt_uint32_t); i ++) { ((rt_uint32_t *)stack_frame)[i] = 0xdeadbeef;[/i] [i] }[/i] /* Initialize the registers automatically saved when an exception occurs*/ stack_frame-&gt;exception_stack_frame.r0 = (unsigned long)parameter; /* r0 : argument */ stack_frame-&gt;exception_stack_frame.r1 = 0; /* r1 */ stack_frame-&gt;exception_stack_frame.r2 = 0; /* r2 */ stack_frame-&gt;exception_stack_frame.r3 = 0; /* r3 */ stack_frame-&gt;exception_stack_frame.r12 = 0; /* r12 */ stack_frame-&gt;exception_stack_frame.lr = 0; /* lr */ stack_frame-&gt;exception_stack_frame.pc = (unsigned long)tentry; /* entry point, pc */ stack_frame-&gt;exception_stack_frame.psr = 0x01000000L; /* PSR */ /* Return thread stack pointer*/ return stk; }
复制代码
The following are the definitions of error codes:
  1. /* ************************************************************************* * Error code definition**************************************************************** */ /* RT-Thread error code redefinition*/ #define RT_EOK 0 /**&lt; There is no error */ #define RT_ERROR 1 /**&lt; A generic error happens */ #define RT_ETIMEOUT 2 /**&lt; Timed out */ #define RT_EFULL 3 /**&lt; The resource is full */ #define RT_EEMPTY 4 /**&lt; The resource is empty */ #define RT_ENOMEM 5 /**&lt; No memory */ #define RT_ENOSYS 6 /**&lt; No system */ #define RT_EBUSY 7 /**&lt; Busy */ #define RT_EIO 8 /**&lt; IO error */ #define RT_EINTR 9 /**&lt; Interrupted system call */ #define RT_EINVAL 10 /**&lt; Invalid argument */
复制代码
The following initializes the thread in the main function:
  1. int main(void) { /* Hardware initialization*/ /* Put hardware-related initialization here. If it is software simulation, there is no related initialization code*/ /* Scheduler initialization*/ rt_system_scheduler_init(); /* Initialize thread*/ rt_thread_init( &amp;rt_flag1_thread, /* Thread control block*/ flag1_thread_entry, /* Thread entry address*/ RT_NULL, /* Thread parameter*/ &amp;rt_flag1_thread_stack[0], /* thread stack starting address*/ sizeof(rt_flag1_thread_stack) ); /* thread stack size in bytes*/ /* insert thread into ready list*/ rt_list_insert_before( &amp;(rt_thread_priority_table[0]),&amp;(rt_flag1_thread.tlist) ); /* initialize thread*/ rt_thread_init( &amp;rt_flag2_thread, /* thread control block*/ flag2_thread_entry, /* thread entry address*/ RT_NULL, /* thread parameter*/ &amp;rt_flag2_thread_stack[0], /* thread stack starting address*/ sizeof(rt_flag2_thread_stack) ); /* thread stack size in bytes*/ /* insert thread into ready list*/ rt_list_insert_before( &amp;(rt_thread_priority_table[1]),&amp;(rt_flag2_thread.tlist) ); /* Start the system scheduler*/ rt_system_scheduler_start(); }
复制代码
Since this chapter contains a lot of content and is important, I will divide it into multiple issues to study this chapter. Today, I will introduce it here. Summary: This article mainly sorts out the thread definition of RT-Thread and how to create a thread. Creating a thread includes: defining the thread stack, defining the thread function, defining the thread control block, implementing the thread creation function, etc. It covers the knowledge of pointers, stacks, and doubly linked lists of data structures, and involves C language structures and other contents. At the same time, combined with the rt-thread source code, we learned the design and implementation of rt-thread about these contents. The following will discuss "6.4 Implementing the Ready List, 6.5 Implementing the Scheduler, 6.6 Implement the main function" and other contents for study and sorting. This content is originally created by EEWORLD forum netizen Media Student. If you need to reprint or use it for commercial purposes, you must obtain the author's consent and indicate the source


Latest reply

I would like to ask you, is the thread created in a separate .c file?  Details Published on 2019-5-6 14:02
 

103

Posts

0

Resources
2
 
I would like to ask you, is the thread created in a separate .c file?
 
Personal signature坚持自己的坚持,终究会有拨开云雾的一天
 
 

530

Posts

4

Resources
3
 
[url=forum.php?mod=redirect&goto=findpost&pid=2867439&ptid=1075707]Shen Tingting published on 2019-5-6 14:02[/ url] I want to ask you, is the thread created in a separate .c file?
Once the library is built, it can be used anywhere. To give you an example of wildfire:
  1. /** ************************************ ********************************* * @file main.c * @author fire * [url=home.php ?mod=space&uid=252314]@version[/url] V1.0 * [url=home.php?mod=space&uid=311857]@date[/url] 2018-xx-xx * [url=home.php?mod =space&uid=159083]@brief[/url] RT-Thread 3.0 + STM32 project template************************************ ************************************ * @attention * * Experimental platform: Wildfire F429 Challenger STM32 development board* Forum:[url]http://www.firebbs.cn[/url] * Taobao:[url]https://fire-stm32.taobao.com[/url] * ****** *************************************************** ****************** */ /* ********************************** ***************************************** * Included header files**** *************************************************** ******************* */ #include "board.h" #include "rtthread.h" /* ************* *************************************************** ********** *Variables****************************************** ************************************* */ /* Define thread control block */ static rt_thread_t led1_thread = RT_NULL ; /* *********************************************** ****************************** * Function declaration********************** *************************************************** ** */ static void led1_thread_entry(void* parameter); /* *********************************** ************************************ * main function************ *************************************************** **************** */ /** * @brief Main function* @param None* @retval None*/ int main(void) { /* * Development board hardware initialization, RTT system The initialization has been completed before the main function, * that is, in the rtthread_startup() function in the component.c file. * So in the main function, you only need to create the thread and start the thread. */ led1_thread = /* Thread control block pointer */ rt_thread_create( "led1", /* Thread name */ led1_thread_entry, /* Thread entry function */ RT_NULL, /* Thread entry function parameters */ 512, /* Thread stack size */ 3, /* Thread priority*/ 20); /* Thread time slice*/ /* Start thread and enable scheduling*/ if (led1_thread != RT_NULL) rt_thread_startup(led1_thread); else return -1; } /* ********************************************************************** * Thread definition**************************************************************** */ static void led1_thread_entry(void* parameter) { while (1) { LED1_ON; rt_thread_delay(500); /* Delay 500 ticks */ LED1_OFF; rt_thread_delay(500); /* Delay 500 ticks */ } } /************************************END OF FILE****************************/
复制代码
 
 
 

Just looking around
Find a datasheet?

EEWorld Datasheet Technical Support

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号
快速回复 返回顶部 Return list