RT-Thread几个不得不知的知识

启动流程

1.上电;
2.运行复位函数Reset_Hhandler();
3.c库函数_mian(),初始化系统堆和栈;
4.执行 s u b sub submain函数(main扩展函数,可在执行main之前执行submain,做一些硬件初始化等预操作,是keil自带的指令);

/* re-define main function */
int $Sub$$main(void)
{
    rtthread_startup();
    return 0;
}

5.关中断rt_hw_interrupt_disable();
6.启动rtthread_startup():
[1 ] 关中断rt_hw_interrupt_disable();
[2 ] 硬件初始化rt_hw_board_init();
[3 ] 显示版本rt_show_version();
[4 ] 系统定时器初始化rt_system_timer_init();
[5 ] 调度器初始化rt_system_scheduler_init();
[6 ] 创建初始化线程rt_application_init();
[7 ] 创建定时器线程rt_system_timer_thread_init();
[8 ] 创建空闲线程rt_thread_idle_init();
[9 ] 开启调度器rt_system_scheduler_start();

int rtthread_startup(void)
{
    rt_hw_interrupt_disable();

    /* board level initialization
     * NOTE: please initialize heap inside board initialization.
     */
    rt_hw_board_init();

    /* show RT-Thread version */
    rt_show_version();

    /* timer system initialization */
    rt_system_timer_init();

    /* scheduler system initialization */
    rt_system_scheduler_init();

#ifdef RT_USING_SIGNALS
    /* signal system initialization */
    rt_system_signal_init();
#endif

    /* create init_thread */
    rt_application_init();

    /* timer thread initialization */
    rt_system_timer_thread_init();

    /* idle thread initialization */
    rt_thread_idle_init();

    /* start scheduler */
    rt_system_scheduler_start();

    /* never reach here */
    return 0;
}

在上述 [6 ] 创建初始化线程rt_application_init()中,实际创建了一个main线程,如图:

void rt_application_init(void)
{
    rt_thread_t tid;

#ifdef RT_USING_HEAP
    tid = rt_thread_create("main", main_thread_entry, RT_NULL,
                           RT_MAIN_THREAD_STACK_SIZE, RT_MAIN_THREAD_PRIORITY, 20);
    RT_ASSERT(tid != RT_NULL);
#else
    rt_err_t result;

    tid = &main_thread;
    result = rt_thread_init(tid, "main", main_thread_entry, RT_NULL,
                            main_stack, sizeof(main_stack), RT_MAIN_THREAD_PRIORITY, 20);
    RT_ASSERT(result == RT_EOK);
	
    /* if not define RT_USING_HEAP, using to eliminate the warning */
    (void)result;
#endif

    rt_thread_startup(tid);
}

点击线程处理函数“main_thread_entry”,跳转至该线程处理函数,发现执行此线程会进行组件的初始化(INIT_BOARD_EXPORT(fn)、INIT_DEVICE_EXPORT(fn)、。。。、INIT_APP_EXPORT(fn))。然后调用supermain()函数(与submain()对应),去到main()。

/* the system main thread */
void main_thread_entry(void *parameter)
{
    extern int main(void);
    extern int $Super$$main(void);

    /* RT-Thread components initialization */
    rt_components_init();

    /* invoke system main function */
#if defined(__CC_ARM) || defined(__CLANG_ARM)
    $Super$$main(); /* for ARMCC. */
#elif defined(__ICCARM__) || defined(__GNUC__)
    main();
#endif
}

当然,由于在 [6 ] 创建初始化线程rt_application_init()时,系统调度器并没有开启,所以该线程在上述 [9 ] 开启调度器rt_system_scheduler_start()之后才会执行。
main线程执行到最后(完成所有应用线程的创建),通过LR寄存器指定的链接地址退出(如下图),rt_thread_exit()会把main线程占用的内存空间释放。
在这里插入图片描述

线程

1.一系列独立线程的集合,每个线程在自己的环境中运行,具有独立的栈;
2.在任何时刻,只有一个线程得到运行;
3.线程执行环境(寄存器值、堆栈内容等)保存在线程堆栈中;

#ifdef RT_USING_HEAP
/**
 * This function will create a thread object and allocate thread object memory
 * and stack.
 *
 * @param name the name of thread, which shall be unique
 * @param entry the entry function of thread
 * @param parameter the parameter of thread enter function
 * @param stack_size the size of thread stack
 * @param priority the priority of thread
 * @param tick the time slice if there are same priority thread
 *
 * @return the created thread object
 */
rt_thread_t rt_thread_create(const char *name,
                             void (*entry)(void *parameter),
                             void       *parameter,
                             rt_uint32_t stack_size,
                             rt_uint8_t  priority,
                             rt_uint32_t tick)
{
    struct rt_thread *thread;
    void *stack_start;

    thread = (struct rt_thread *)rt_object_allocate(RT_Object_Class_Thread,
                                                    name);
    if (thread == RT_NULL)
        return RT_NULL;

    stack_start = (void *)RT_KERNEL_MALLOC(stack_size);
    if (stack_start == RT_NULL)
    {
        /* allocate stack failure */
        rt_object_delete((rt_object_t)thread);

        return RT_NULL;
    }

    _rt_thread_init(thread,
                    name,
                    entry,
                    parameter,
                    stack_start,
                    stack_size,
                    priority,
                    tick);

    return thread;
}
RTM_EXPORT(rt_thread_create);

调度器

1.中断处理函数、调度器上锁部分、禁止中断的代码不可抢占,其余都可抢占,包括调度器自身;
2.基于位图的优先级算法,时间复杂度为O(1),响应时间与就绪线程的多少无关;

线程状态

1.初始态:创建线程时;
2.就绪态:等待cpu,在就绪列表中;
3.运行态:占用cpu,正在运行;
4.挂起态:在挂起列表中;
5.关闭态:运行结束,系统回收资源;
在这里插入图片描述
注:
1.当前已经挂起的线程,不可重复挂起;
2.挂起态不可直接进入运行态,需参照挂起态------就绪态------运行态的步骤;
3.只有运行态、挂起态线程可进入关闭态;
4.挂起:
[1].主动挂起:调用delay、suspend等函数,主动挂起。调用resume函数恢复;
[2].被动挂起:调用sem_take、mb_recv、mutex_take、event_recv等函数,且资源不可用时,被动挂起;
5.若suspend线程本身,需要在suspend之后调用schedule函数进行调度;

空闲线程

创建空闲线程(启动时创建)

/**
 * @ingroup SystemInit
 *
 * This function will initialize idle thread, then start it.
 *
 * @note this function must be invoked when system init.
 */
void rt_thread_idle_init(void)
{
    /* initialize thread */
    rt_thread_init(&idle,
                   "tidle",
                   rt_thread_idle_entry,
                   RT_NULL,
                   &rt_thread_stack[0],
                   sizeof(rt_thread_stack),
                   RT_THREAD_PRIORITY_MAX - 1,
                   32);

    /* startup */
    rt_thread_startup(&idle);
}

空闲线程处理函数

static void rt_thread_idle_entry(void *parameter)
{
    while (1)
    {

#ifdef RT_USING_IDLE_HOOK
        rt_size_t i;

        for (i = 0; i < RT_IDEL_HOOK_LIST_SIZE; i++)
        {
            if (idle_hook_list[i] != RT_NULL)
            {
                idle_hook_list[i]();
            }
        }
#endif

        rt_thread_idle_excute();
#ifdef RT_USING_PM        
        rt_system_power_manager();
#endif
    }
}

1.空闲线程是系统在没有其他工作时,自动进入的系统线程;
2.是系统中唯一不允许阻塞,不允许挂起、不允许delay的线程(必须保证系统有一个可以随时进入运行的线程);
3.在空闲线程中包含钩子函数,可自定义一下非紧急的处理函数;
4.在空闲线程中对系统的栈内存释放,对象删除等处理,如下图;

/**
 * @ingroup Thread
 *
 * This function will perform system background job when system idle.
 */
void rt_thread_idle_excute(void)
{
    /* Loop until there is no dead thread. So one call to rt_thread_idle_excute
     * will do all the cleanups. */
    while (_has_defunct_thread())
    {
        rt_base_t lock;
        rt_thread_t thread;
#ifdef RT_USING_MODULE
        struct rt_dlmodule *module = RT_NULL;
#endif
        RT_DEBUG_NOT_IN_INTERRUPT;

        /* disable interrupt */
        lock = rt_hw_interrupt_disable();

        /* re-check whether list is empty */
        if (_has_defunct_thread())
        {
            /* get defunct thread */
            thread = rt_list_entry(rt_thread_defunct.next,
                                   struct rt_thread,
                                   tlist);
#ifdef RT_USING_MODULE
            module = (struct rt_dlmodule*)thread->module_id;
            if (module)
            {
                dlmodule_destroy(module);
            }
#endif
            /* remove defunct thread */
            rt_list_remove(&(thread->tlist));

            /* lock scheduler to prevent scheduling in cleanup function. */
            rt_enter_critical();

            /* invoke thread cleanup */
            if (thread->cleanup != RT_NULL)
                thread->cleanup(thread);

#ifdef RT_USING_SIGNALS
            rt_thread_free_sig(thread);
#endif

            /* if it's a system object, not delete it */
            if (rt_object_is_systemobject((rt_object_t)thread) == RT_TRUE)
            {
                /* detach this object */
                rt_object_detach((rt_object_t)thread);
                /* unlock scheduler */
                rt_exit_critical();

                /* enable interrupt */
                rt_hw_interrupt_enable(lock);

                return;
            }

            /* unlock scheduler */
            rt_exit_critical();
        }
        else
        {
            /* enable interrupt */
            rt_hw_interrupt_enable(lock);

            /* may the defunct thread list is removed by others, just return */
            return;
        }

        /* enable interrupt */
        rt_hw_interrupt_enable(lock);

#ifdef RT_USING_HEAP
        /* release thread's stack */
        RT_KERNEL_FREE(thread->stack_addr);
        /* delete thread object */
        rt_object_delete((rt_object_t)thread);
#endif
    }
}

中断服务函数

RT-Thread中程序运行的上下文包括:
1.中断服务函数;
2.普通线程;
3.空闲线程;

中断服务函数:
1.中断服务函数运行在非线程的执行环境下,一般为芯片的一种特殊运行模式(特权模式);
2.中断服务函数不允许任何阻塞,要保持精简短小,快进快出,一般只用来标记;
3.中断服务函数的优先级高于全部线程,不管该中断优先级如何,不管线程优先级如何;
4.若支持中断嵌套,在执行中断过程中,发生了更高优先级的中断,则先去执行高优先级中断,结束之后再执行原中断;

优先级

线程优先级的设置:
需要紧急处理、执行时间短的线程优先级应该设置高一点;

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值