打印
[应用相关]

RT-Thread 基于stm32 读后感

[复制链接]
2605|62
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
dingbo95|  楼主 | 2018-10-26 21:24 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
什么是线程?
在单片机裸机系统中, 系统的主体就是 main 函数里面顺序执行的无限循环,这个无限循环里面 CPU 按照顺序完成各种事情。在多线程系统中,我们根据功能的不同,把整个系统分割成一个个独立的且无法返回的函数,这个函数我们称为线程。说白了就是把我们之前现在main函数的任务放入while(1)死循环中,通过调用线程切换函数来切换不同的线程。


沙发
dingbo95|  楼主 | 2018-10-26 21:25 | 只看该作者
线程大概形式如下:
/***********************线程的主要形式***********************/

void  thread_entry(void *parg)
{
       /* 线程主体,无限循环
    while(1)
    {
       /* 线程主体代码*/   
    }

}


使用特权

评论回复
板凳
dingbo95|  楼主 | 2018-10-26 21:26 | 只看该作者
2. 怎么创建线程?
 比较复杂的事情,大致分为:

                                                    1.定义线程栈                     2.定义线程函数  

                                                    3.定义线程控制块             4.实现线程创建函数

使用特权

评论回复
地板
dingbo95|  楼主 | 2018-10-26 21:27 | 只看该作者
3.定义线程的栈
多线程操作系统中,每个线程都是独立的,互不干扰,所以要为每个线程分配独立的栈空间,这个栈空间通常是一个预先定义好的全局数组, 也可以是动态分配的一段内存空间,但它们都存在于 RAM 中。

使用特权

评论回复
5
dingbo95|  楼主 | 2018-10-26 21:28 | 只看该作者
定义两个线程栈如下:
// 定义线程栈 大小设置为512

rt_uint8_t  rt_flag1_thread_stack[512];
rt_uint8_t  rt_flag2_thread_stack[512];


使用特权

评论回复
6
dingbo95|  楼主 | 2018-10-26 21:30 | 只看该作者
4.定义线程函数
线程是一个独立的函数,函数主体无限循环不能返回。

使用特权

评论回复
7
dingbo95|  楼主 | 2018-10-26 21:31 | 只看该作者
定义相关线程函数如下:
/********************************线程函数******************************/

/* 延时函数*/

void delay(uint32_t  count)
{
   for(;count!=0;count--);
}


/* 线程 1 */
void flag1_thread_entry(void *p_arg)
{
  while(1)
    {
      flag1=1;
        delay(100);
        flag1=0;
        delay(100);
        
     /* 线程切换*/
   rt_schedule();        
    }
}

/* 线程 2 */
void flag2_thread_entry(void *p_arg)
{
  while(1)
    {
       flag2=1;
         delay(100);
         flag2=0;
         delay(100);
         /* 线程切换*/
         rt_schedule();   
    }
}


/*******************************************************************************/



使用特权

评论回复
8
dingbo95|  楼主 | 2018-10-26 21:34 | 只看该作者
5.如果要顺利调度线程,需要为每个线程额外定义一个线程控制块,存着线程的所有信息(线程栈指针,线程名称,线程形参)。以后系统对线程的全部操作都是通过线程控制块来实现,这里的线程控制块特别重要,一定牢牢掌握。为了使每个线程方便定义线程控制块实体,RT—Thread 在rtdef.h中定义了一个新的数据类型,并将其声明。

使用特权

评论回复
9
dingbo95|  楼主 | 2018-10-26 21:35 | 只看该作者
rtdef.h中定义了一个新的数据类型如下:
/* 线程控制块声明 */
struct  rt_thread
{
      void        *sp;          /* 线程栈指针*/
          void        *entry;       /*线程入口地址*/
          void        *parameter;   /*线程形参*/
          void        *stack_adder; /*线程栈起始地址*/
          rt_uint32_t  stack_size;  /*线程栈大小*/
};
typedef struct rt_thread  *rt_thread_t;


使用特权

评论回复
10
dingbo95|  楼主 | 2018-10-26 21:37 | 只看该作者
在主函数 main 中还需要定义两个 线程控制块,代码如下:
/* 定义两个线程控制块,对应之前定义的两个线程 */

struct rt_thread  rt_flag1_thread;
struct rt_thread  rt_flag2_thread;


使用特权

评论回复
11
dingbo95|  楼主 | 2018-10-26 21:38 | 只看该作者
6.线程初始化函数
前面我们坑此坑次的定义了 线程函数实体,线程的栈,线程控制块,需要将三者联系在一起的就是线程初始化函数,这样才能由系统统一调度。线程初始化函数: rt_thread_init()  改函数在thread.c文件中

使用特权

评论回复
12
dingbo95|  楼主 | 2018-10-26 21:38 | 只看该作者

代码如下:

/*  线程出初始化函数 */

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(&(thread->tlist));
         thread->entry =(void*)entry;
         thread->parameter =parameter;
       
         thread->stack_adder = stack_start;
         thread->stack_size = stack_size;
       
        thread->sp =
        (void*)rt_hw_stack_init(thread->entry,
                                      thread->parameter,
        (void*)((char*)thread->stack_adder+thread->stack_size-4));
        return RT_EOK;
       

}


使用特权

评论回复
13
dingbo95|  楼主 | 2018-10-26 21:41 | 只看该作者
在主函数中建立两个初始化线程,代码如下
 /* 初始化线程*/


         rt_thread_init(&rt_flag1_thread,                /* 线程控制块*/
                        flag1_thread_entry ,             /* 线程入口参数*/
                        RT_NULL,                         /* 线程形参*/
                        &rt_flag1_thread_stack[0],       /* 线程栈起始地址*/
                        sizeof(rt_flag1_thread_stack));  /*线程栈大小,单位为字节*/
         

         rt_thread_init(&rt_flag2_thread,                /* 线程控制块*/
                        flag2_thread_entry ,             /* 线程入口参数*/
                        RT_NULL,                         /* 线程形参*/
                        &rt_flag2_thread_stack[0],       /* 线程栈起始地址*/
                        sizeof(rt_flag2_thread_stack));  /*线程栈大小,单位为字节*/


使用特权

评论回复
14
dingbo95|  楼主 | 2018-10-26 21:42 | 只看该作者
7. 定义就绪列表
线程创建好后,需要将线程添加到就绪列表里面,表示线程已经就绪,系统随时可以调度。

使用特权

评论回复
15
dingbo95|  楼主 | 2018-10-26 21:43 | 只看该作者
RT-Thread定义的就绪列表如下:
/*  线程就绪列表如下 
**  RT_THREAD_PRIORITY_MAX 在rtconfig.h中默认定义为32  决定最大线程优先级
*/

rt_list_t rt_thread_priority_table[RT_THREAD_PRIORITY_MAX];



使用特权

评论回复
16
dingbo95|  楼主 | 2018-10-26 21:43 | 只看该作者
8.将线程插入到就绪列表
将线程插入到就绪列表就是通过线程控制块tlist这个节点插入到就绪列表来实现的。

使用特权

评论回复
17
dingbo95|  楼主 | 2018-10-26 21:45 | 只看该作者
在初始化线程代码中添加 将线程插入到就绪列表的操作如下:
 /* 初始化线程*/
         rt_thread_init(&rt_flag1_thread,                /* 线程控制块*/
                        flag1_thread_entry ,             /* 线程入口参数*/
                        RT_NULL,                         /* 线程形参*/
                        &rt_flag1_thread_stack[0],       /* 线程栈起始地址*/
                        sizeof(rt_flag1_thread_stack));  /*线程栈大小,单位为字节*/

         /* 将线程插入到就绪列表中 */
         rt_list_insert_before(&(rt_thread_priority_table[0]),&(rt_flag1_thread.tlist));
         
     rt_thread_init(&rt_flag2_thread,                /* 线程控制块*/
                        flag2_thread_entry ,             /* 线程入口参数*/
                        RT_NULL,                         /* 线程形参*/
                        &rt_flag2_thread_stack[0],       /* 线程栈起始地址*/
                        sizeof(rt_flag2_thread_stack));  /*线程栈大小,单位为字节*/
         
     /* 将线程插入到就绪列表中 */
         rt_list_insert_before(&(rt_thread_priority_table[1]),&(rt_flag2_thread.tlist));


使用特权

评论回复
18
dingbo95|  楼主 | 2018-10-26 21:45 | 只看该作者
就绪列表的下标对应的是线程的优先级,目前线程还不支持优先级,选择flag1 线程插入到就绪列表为0的链表中,选择flag2插入到就绪列表为1的链表中。

使用特权

评论回复
19
chenqiang10| | 2018-10-26 22:00 | 只看该作者
支持国产 ,支持RTT

使用特权

评论回复
20
chenqiang10| | 2018-10-26 22:00 | 只看该作者
我也要好好研究一下RTT,

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

52

主题

1197

帖子

5

粉丝