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

[复制链接]
692|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
创建:
  1. rt_thread_t rt_thread_create(const char* name,
  2.                             void (*entry)(void* parameter),
  3.                             void* parameter,
  4.                             rt_uint32_t stack_size,
  5.                             rt_uint8_t priority,
  6.                             rt_uint32_t tick);



关闭:
  1. rt_err_t rt_thread_delete(rt_thread_t thread);



静态初始化:
  1. rt_err_t rt_thread_init(struct rt_thread* thread,
  2.                         const char* name,
  3.                         void (*entry)(void* parameter), void* parameter,
  4.                         void* stack_start, rt_uint32_t stack_size,
  5.                         rt_uint8_t priority, rt_uint32_t tick);


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

线程睡眠
  1. rt_err_t rt_thread_sleep(rt_tick_t tick);
  2. rt_err_t rt_thread_delay(rt_tick_t tick);
  3. 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-初始化两个线程

  1. static void rt_init_thread_entry(void *parameter)
  2. {
  3.         rt_thread_t led_thread, printf_thread;

  4. /* Initialization RT-Thread Components */
  5. #ifdef RT_USING_COMPONENTS_INIT
  6.     rt_components_init();
  7. #endif

  8.     /* Create led thread */
  9.     led_thread = rt_thread_create("led",
  10.                                   led_thread_entry, RT_NULL,
  11.                                   256, 20, 20);
  12.     if (led_thread != RT_NULL)
  13.         rt_thread_startup(led_thread);

  14.     printf_thread = rt_thread_create("print period",
  15.                                      printf_period, RT_NULL,
  16.                                      256, 20, 20);
  17.     if (printf_thread != RT_NULL)
  18.         rt_thread_startup(printf_thread);
  19. }


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


3-在led线程里面唤醒
  1. static void led_thread_entry(void *parameter)
  2. {
  3.     rt_hw_led_init();
  4.     rt_kprintf("start\n");
  5.     while (1)
  6.     {
  7.         rt_hw_led_on();
  8.         rt_thread_delay(RT_TICK_PER_SECOND);
  9.         rt_hw_led_off();
  10.         rt_thread_delay(RT_TICK_PER_SECOND);
  11.         rt_thread_resume(printf_thread);
  12.     }
  13. }


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

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

  1. static void printf_period(void *parameter)
  2. {
  3.     rt_kprintf("heart break start\n");
  4.     while (1)
  5.     {
  6.         rt_kprintf("heart break\n");
  7.         //        
  8.         rt_thread_suspend(rt_thread_self());
  9.         rt_schedule();
  10.     }
  11. }

您需要登录后才可以回帖 登录 | 注册

本版积分规则

15

主题

73

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部