• Rt-Thread 移植6--多线程(KF32)


    6.1 就绪列表

    6.1.1 线程就绪优先级组

    线程优先级表的索引对应的线程的优先级。
    在这里插入图片描述
    为了快速的找到线程在线程优先级表的插入和移出的位置,RT-Thread专门设计了一个线程就绪优先级组。线程就绪优先组是一个32位的整型数,每一个位对应一个优先级,最多表示32个优先级

    rt_uint32_t  rt_thread_ready_priority_group;
    
    • 1

    在这里插入图片描述

    6.1.2 寻找优先级最高的线程

    在这里插入图片描述
    在这里插入图片描述

    从图中看出,第一个置1的位是位1,即表示此时就绪的线程当中,优先级最高的线程1,然后调度器从线程优先级表的索引1下去除线程1的线程控制块,从而切换到线程1.
    kservice.c中

    const rt_uint8_t __lowest_bit_bitmap[] =
    {
        /* 00 */ 0, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
        /* 10 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
        /* 20 */ 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
        /* 30 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
        /* 40 */ 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
        /* 50 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
        /* 60 */ 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
        /* 70 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
        /* 80 */ 7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
        /* 90 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
        /* A0 */ 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
        /* B0 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
        /* C0 */ 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
        /* D0 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
        /* E0 */ 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
        /* F0 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0
    };
    
    /**
     * This function finds the first bit set (beginning with the least significant bit)
     * in value and return the index of that bit.
     *
     * Bits are numbered starting at 1 (the least significant bit).  A return value of
     * zero from any of these functions means that the argument was zero.
     *
     * @return return the index of the first bit set. If value is 0, then this function
     * shall return 0.
     */
    int __rt_ffs(int value)
    {
        if (value == 0) return 0;
    
        if (value & 0xff)
            return __lowest_bit_bitmap[value & 0xff] + 1;
    
        if (value & 0xff00)
            return __lowest_bit_bitmap[(value & 0xff00) >> 8] + 9;
    
        if (value & 0xff0000)
            return __lowest_bit_bitmap[(value & 0xff0000) >> 16] + 17;
    
        return __lowest_bit_bitmap[(value & 0xff000000) >> 24] + 25;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45

    6.1.3 线程优先级表

    scheduler.c

    rt_list_t rt_thread_priority_table[RT_THREAD_PRIORITY_MAX];
    
    
    • 1
    • 2

    在这里插入图片描述
    将线程插入到线程优先级表和移出分别由scheduler.c的rt_schedule_insert_thread()和rt_schedule_remove_thread()这两个函数实现。

    void rt_schedule_insert_thread(struct rt_thread *thread)
    {
        register rt_base_t temp;
    
    
        /* disable interrupt */
        temp = rt_hw_interrupt_disable();
    
        /* change stat */
        thread->stat = RT_THREAD_READY | (thread->stat & ~RT_THREAD_STAT_MASK);
    
        /* insert thread to ready list */
        rt_list_insert_before(&(rt_thread_priority_table[thread->current_priority]),
                              &(thread->tlist));
    
    
        /* set priority mask */
    
    
    #if RT_THREAD_PRIORITY_MAX > 32
        rt_thread_ready_table[thread->number] |= thread->high_mask;
    #endif
        rt_thread_ready_priority_group |= thread->number_mask;
    
        P_DBG("insert thread %x grout %x\n",thread,rt_thread_ready_priority_group);
        /* enable interrupt */
        rt_hw_interrupt_enable(temp);
    }
    
    /*
     * This function will remove a thread from system ready queue.
     *
     * @param thread the thread to be removed
     *
     * @note Please do not invoke this function in user application.
     */
    void rt_schedule_remove_thread(struct rt_thread *thread)
    {
        register rt_base_t temp;
    
    
    
        /* disable interrupt */
        temp = rt_hw_interrupt_disable();
    
    
        /* remove thread from ready list */
        rt_list_remove(&(thread->tlist));
        if (rt_list_isempty(&(rt_thread_priority_table[thread->current_priority])))
        {
    
            rt_thread_ready_priority_group &= ~thread->number_mask;
    
        }
    
        /* enable interrupt */
        rt_hw_interrupt_enable(temp);
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59

    6.2 修改代码

    6.2.1 修改线程控制块

    struct rt_thread
    {
    	char name[RT_NAME_MAX];
    	rt_uint8_t type;
    	rt_uint8_t flag;
    	rt_list_t list;
    	void        *sp;	          /* 线程栈指针 */
    	void        *entry;	          /* 线程入口地址 */
    	void        *parameter;	      /* 线程形参 */	
    	void        *stack_addr;      /* 线程起始地址 */
    	rt_uint32_t stack_size;       /* 线程栈大小,单位为字节 */
    	
    	rt_list_t   tlist;            /* 线程链表节点 */
    #if TEST_USE_TICK_ENABLE
    	rt_ubase_t init_tick;
    	rt_ubase_t remaining_tick;
    #endif
    	**rt_uint8_t current_priority;
    	rt_uint8_t init_priority;
    	rt_uint32_t number_mask;
    	rt_err_t error;
    	rt_uint8_t stat;**
    
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    rtdef.h中定义错误码

    #define RT_EOK                          0               /**< There is no error */
    #define RT_ERROR                        1               /**< A generic error happens */
    #define RT_ETIMEOUT                     2               /**< Timed out */
    #define RT_EFULL                        3               /**< The resource is full */
    #define RT_EEMPTY                       4               /**< The resource is empty */
    #define RT_ENOMEM                       5               /**< No memory */
    #define RT_ENOSYS                       6               /**< No system */
    #define RT_EBUSY                        7               /**< Busy */
    #define RT_EIO                          8               /**< IO error */
    #define RT_EINTR                        9               /**< Interrupted system call */
    #define RT_EINVAL                       10              /**< Invalid argument */
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    定义线程状态

    #define RT_THREAD_INIT                  0x00                /**< Initialized status */
    #define RT_THREAD_READY                 0x01                /**< Ready status */
    #define RT_THREAD_SUSPEND               0x02                /**< Suspend status */
    #define RT_THREAD_RUNNING               0x03                /**< Running status */
    #define RT_THREAD_BLOCK                 RT_THREAD_SUSPEND   /**< Blocked status */
    #define RT_THREAD_CLOSE                 0x04                /**< Closed status */
    #define RT_THREAD_STAT_MASK             0x0f
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    修改rt_system_scheduler_init()

    void rt_system_scheduler_init(void)
    {
    
    
    
    	register rt_base_t offset;
    	for(offset = 0; offset < RT_THREAD_PRIORITY_MAX;offset++)
    	{
    		rt_list_init(&rt_thread_priority_table[offset]);
    	}
    	rt_current_priority = RT_THREAD_PRIORITY_MAX - 1;
    	rt_current_thread = RT_NULL;
    	rt_thread_ready_priority_group = 0;
    
    	/* 初始化线程休眠列表,当线程创建好没有启动之前会被放入到这个列表 */
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    6.2.3 修改线程初始化函数rt_thread_init()

    rt_err_t rt_thread_init(struct rt_thread *thread,const char *name,
                            void (*entry)(void *parameter),
                            void             *parameter,
                            void             *stack_start,
                            rt_uint32_t       stack_size,
                            **rt_uint8_t priority**)
    {
    	rt_object_init((rt_object_t)thread,RT_Object_Class_Thread,name);
    	rt_list_init(&(thread->tlist));
    
    	thread->entry = (void *)entry;
    	thread->parameter = parameter;
    
    	thread->stack_addr = stack_start;
    	thread->stack_size = stack_size;
    
    	/* 初始化线程栈,并返回线程栈指针 */
    	thread->sp = (void *)rt_hw_stack_init( thread->entry,
    		                                   thread->parameter,
    							               (void *)((char *)thread->stack_addr + thread->stack_size - 4) );
    	**thread->init_priority = priority;
    	thread->current_priority = priority;
    	thread->number_mask = 0;
    	thread->error = RT_EOK;
    	thread->stat = RT_THREAD_INIT;**
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    6.2.4 添加线程启动函数rt_thread_startup()

    rt_err_t rt_thread_startup(rt_thread_t thread)
    {
    	thread->current_priority = thread->init_priority;
    	thread->number_mask = 1L << thread->current_priority;
    	thread->stat = RT_THREAD_SUSPEND;
    	rt_thread_resume(thread);
    	if(rt_thread_self() != RT_NULL)
    	{
    		rt_schedule();
    	}
    }
    rt_err_t rt_thread_resume(rt_thread_t thread)
    {
    	register rt_base_t temp;
    	if((thread->stat & RT_THREAD_STAT_MASK) != RT_THREAD_SUSPEND)
    	{
    		return -RT_ERROR;
    	}
    	temp = rt_hw_interrupt_disable();
    	rt_list_remove(&(thread->tlist));
    
    	rt_hw_interrupt_enable(temp);
    	rt_schedule_insert_thread(thread);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    6.2.5 修改空闲线程初始化函数rt_thread_idle_init()

    void rt_thread_idle_init(void)
    {
    	    rt_thread_init(&idle,"idle",rt_thread_idle_entry,RT_NULL,&rt_thread_stack[0],sizeof(rt_thread_stack),RT_THREAD_PRIORITY_MAX - 1);
    
    	**rt_thread_startup(&idle);**
    
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    6.2.6 修改启动系统调度器函数rt_system_scheduler_start()

    不再是手动指定第一个需要运行的线程,而是根据优先级来决定第一个运行的线程。

    void rt_system_scheduler_start(void)
    {
    
    	register struct rt_thread *to_thread;
    	register rt_ubase_t highest_ready_priority;
    	highest_ready_priority = __rt_ffs(rt_thread_ready_priority_group)-1;
    	P_DBG("first start pri %d\n",highest_ready_priority);
    	to_thread = rt_list_entry(rt_thread_priority_table[highest_ready_priority].next,struct rt_thread,tlist);
    	rt_current_thread = to_thread;
    	rt_hw_context_switch_to((rt_uint32_t)&to_thread->sp);
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    6.2.7 修改系统调度函数rt_schedule()

    根据优先级来实现

    void rt_schedule(void)
    {
    
    	register rt_base_t temp;
    	rt_base_t level;
    	register rt_ubase_t highest_ready_priority;
    	struct rt_thread *to_thread;
    	struct rt_thread *from_thread;
    	temp = rt_hw_interrupt_disable();
    	highest_ready_priority = __rt_ffs(rt_thread_ready_priority_group)-1;
    	P_DBG("read pri %d\n",highest_ready_priority);
    	to_thread = rt_list_entry(rt_thread_priority_table[highest_ready_priority].next,struct rt_thread,tlist);
    	P_DBG("read tgread %x\n",to_thread);
    	if(to_thread != rt_current_thread)
    	{
    		P_DBG("!= current thread %x\n",rt_current_thread);
    		rt_current_priority = (rt_uint8_t) highest_ready_priority;
    		from_thread = rt_current_thread;
    		rt_current_thread = to_thread;
    		rt_hw_context_switch((rt_uint32_t)&from_thread->sp,(rt_uint32_t)&to_thread->sp);
    		rt_hw_interrupt_enable(temp);
    	}
    	else
    	{
    		rt_hw_interrupt_enable(temp);
    	}
    
    
    
    	/* 产生上下文切换 */
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    6.2.8 修改线程阻塞函数

    
    void rt_thread_delay(rt_tick_t tick)
    {
    	register rt_base_t temp;
    	struct rt_thread *thread;
    	temp = rt_hw_interrupt_disable(); 
    	thread = rt_current_thread;
    	thread->remaining_tick = tick;
    	thread->stat = RT_THREAD_SUSPEND; 
    	rt_thread_ready_priority_group &= ~thread->number_mask;
    	rt_hw_interrupt_enable(temp);
    	rt_schedule();
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    6.2.9 修改时基更i新函数rt_tick_increase()

    void rt_tick_increase(void)
    {
    		rt_ubase_t i;
    	struct rt_thread *thread;
    	rt_tick++;
    	for(i = 0;i < RT_THREAD_PRIORITY_MAX;i++)
    	{
    		thread = rt_list_entry(rt_thread_priority_table[i].next,struct rt_thread,tlist);
    		if(thread->remaining_tick > 0)
    		{
    			thread->remaining_tick--;
    			if(thread->remaining_tick == 0)
    			{
    				rt_thread_ready_priority_group |= thread->number_mask;
    			}
    		}
    		rt_schedule();
    	}
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    6.3 main.c

    
    			/* 初始化线程 */
    		rt_thread_init( &rt_flag1_thread,   "flag1",              /* 线程控制块 */
    			                flag1_thread_entry,               /* 线程入口地址 */
    			                RT_NULL,                          /* 线程形参 */
    			                &rt_flag1_thread_stack[0],        /* 线程栈起始地址 */
    			                sizeof(rt_flag1_thread_stack),3 );  /* 线程栈大小,单位为字节 */
    
    
    			/* 将线程插入到就绪列表 */
    		//rt_list_insert_before( &(rt_thread_priority_table[0]),&(rt_flag1_thread.tlist) );
    		P_DBG("thread flag1 %x timer %s\n",&rt_flag1_thread,rt_flag1_thread.thread_timer.parent.name);
    		rt_thread_startup(&rt_flag1_thread);
    			/* 初始化线程 */
    
    		rt_thread_init( &rt_flag2_thread,           "falg2",      /* 线程控制块 */
    			                flag2_thread_entry,               /* 线程入口地址 */
    			                RT_NULL,                          /* 线程形参 */
    			                &rt_flag2_thread_stack[0],        /* 线程栈起始地址 */
    			                sizeof(rt_flag2_thread_stack),4 );  /* 线程栈大小,单位为字节 */
    
    /* 将线程插入到就绪列表 */
    		P_DBG("thread flag1 %x timer %s\n",&rt_flag2_thread,rt_flag2_thread.thread_timer.parent.name);
    
    		//rt_list_insert_before( &(rt_thread_priority_table[1]),&(rt_flag2_thread.tlist) );
    		rt_thread_startup(&rt_flag2_thread);
    			/* 启动系统调度器 */
    		rt_system_scheduler_start();
    
    
    /* 线程1 */
    void flag1_thread_entry( void *p_arg )
    {
    	for( ;; )
    	{
    		P_DBG("flag1 thread\n");
    
    		flag2 = 1;
    		P_DBG("flag1 thread will dela1\n");
    		rt_thread_delay(10);
    		flag2 = 0;
    		P_DBG("flag1 thread will dela2\n");
    		rt_thread_delay(10);
    
    	}
    }
    
    /* 线程2 */
    void flag2_thread_entry( void *p_arg )
    {
    	for( ;; )
    	{
    		P_DBG("flag2 thread\n");
    
    		flag2 = 1;
    		rt_thread_delay(2);
    		flag2 = 0;
    		P_DBG("flag2 thread will dela1\n");
    		rt_thread_delay(2);
    
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
  • 相关阅读:
    攻防世界WEB(二)baby_web、Training-WWW-Robots、PHP2、unserialize3
    基于SSM的高校毕业设计选题管理系统(有报告)。Javaee项目。
    iOS——持久化
    Windows11下载安装vscode并编写第一个页面
    Centos7下harbor的安装部署
    C语言的文件操作
    设计模式六大原则
    【JavaWeb】过滤器和监听器,就这?
    MFC Windows 程序设计[261]之选项文档例程(附源码)
    混合开发架构|原生&Flutter通信
  • 原文地址:https://blog.csdn.net/qq_43650963/article/details/134359653