打印

RT-Thread笔记 1-线程+挂起实验

[复制链接]
453|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
tinnu|  楼主 | 2020-6-12 23:33 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

(一)状态


线程通过调用函数 rt_thread_create/init() 进入到 初始状态(RT_THREAD_INIT)
初始状态的线程通过调用函数 rt_thread_startup() 进入到 就绪状态(RT_THREAD_READY)
就绪状态的线程被调度器调度后进入 运行状态(RT_THREAD_RUNNING)
当处于运行状态的线程调用 rt_thread_delay(),rt_sem_take(),rt_mutex_take(),rt_mb_recv()
等函数或者获取不到资源时,将进入到
挂起状态(RT_THREAD_SUSPEND)
处于挂起状态的线程,如果等待超时依然未能获得资源或由于其他线程释放了资源,那么它将返回到 就绪状态
挂起状态的线程,如果调用 rt_thread_delete/detach() 函数,将更改为 关闭状态(RT_THREAD_CLOSE)
而运行状态的线程,如果运行结束,就会在线程的最后部分执行 rt_thread_exit() 函数,将状态更改为 关闭状态。




(二)API
创建:
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);



关闭:
rt_err_t rt_thread_delete(rt_thread_t thread);



静态初始化:
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_uint32_t tick);


参数        描述
thread        线程句柄,它应该是由 rt_thread_init 进行初始化的线程句柄。
返回        ——
RT_EOK        线程脱离成功
-RT_ERROR        线程脱离失败

线程睡眠
rt_err_t rt_thread_sleep(rt_tick_t tick);
rt_err_t rt_thread_delay(rt_tick_t tick);
rt_err_t rt_thread_mdelay(rt_int32_t ms);



线程挂起
rt_err_t rt_thread_suspend (rt_thread_t thread);

恢复线程
rt_err_t rt_thread_resume (rt_thread_t thread);

控制线程
rt_err_t rt_thread_control(rt_thread_t thread, rt_uint8_t cmd, void* arg);

线程让出资源
rt_thread_yield()         当前线程被置于最末
rt_schedule()        按照优先级放置

获取当前线程
rt_thread_t rt_thread_self(void);


(三)挂起实验
rt_thread_suspend  可以把某个线程挂起,在某个时候恢复
尽管官方不怎么推荐使用者使用这个函数,但毕竟还是有相当的实用性,我目前有这个需求,所以进行了一些尝试。
1-初始化两个线程

static void rt_init_thread_entry(void *parameter)
{
        rt_thread_t led_thread, printf_thread;

/* Initialization RT-Thread Components */
#ifdef RT_USING_COMPONENTS_INIT
    rt_components_init();
#endif

    /* Create led thread */
    led_thread = rt_thread_create("led",
                                  led_thread_entry, RT_NULL,
                                  256, 20, 20);
    if (led_thread != RT_NULL)
        rt_thread_startup(led_thread);

    printf_thread = rt_thread_create("print period",
                                     printf_period, RT_NULL,
                                     256, 20, 20);
    if (printf_thread != RT_NULL)
        rt_thread_startup(printf_thread);
}


2-在printf控制台打印线程里面每次循环都挂起一次
// led thread entry
static void printf_period(void *parameter)
{
    rt_kprintf("heart break start\n");
    while (1)
    {
        rt_kprintf("heart break\n");
        //        
        rt_thread_suspend(rt_thread_self());
    }
}


3-在led线程里面唤醒
static void led_thread_entry(void *parameter)
{
    rt_hw_led_init();
    rt_kprintf("start\n");
    while (1)
    {
        rt_hw_led_on();
        rt_thread_delay(RT_TICK_PER_SECOND);
        rt_hw_led_off();
        rt_thread_delay(RT_TICK_PER_SECOND);
        rt_thread_resume(printf_thread);
    }
}


然而奇怪的事情发生了,串口每隔1s时间打印一串字符,并不是如我想象的那样打印一次立即挂起。

(四)解决方法
仔细查看文档后发现,挂起是不能够立即生效的,想要立即生效要进行上下文调度,可以用rt_schedule 引起这个调度:

static void printf_period(void *parameter)
{
    rt_kprintf("heart break start\n");
    while (1)
    {
        rt_kprintf("heart break\n");
        //        
        rt_thread_suspend(rt_thread_self());
        rt_schedule();
    }
}

使用特权

评论回复

相关帖子

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

本版积分规则

15

主题

68

帖子

0

粉丝