【STM32&RT-Thread零基础入门】 6. 线程创建应用(线程挂起与恢复)

这篇具有很好参考价值的文章主要介绍了【STM32&RT-Thread零基础入门】 6. 线程创建应用(线程挂起与恢复)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

硬件:STM32F103ZET6、ST-LINK、usb转串口工具、4个LED灯、1个蜂鸣器、4个1k电阻、2个按键、面包板、杜邦线


前言

在上一个任务中,通过停止命令把线程删除后,线程在系统中就不存在了,也无法再使线程重新运行。例如输入stop_led_thread命令后,led停止闪烁,但也无法重新开启LED灯闪烁功能。本任务通过修改停止命令的实现代码,同时增加恢复命令,使led灯闪烁功能可以暂停和恢复。


一、RT-Thread相关接口函数

1. 挂起线程

线程挂起是指把线程脱离就绪队列,使线程不参与调度器的调度。线程挂起使用下面的接口函数:

rt_err_t rt_thread_suspend (rt_thread_t thread);

线程挂起接口 rt_thread_suspend() 的参数和返回值见下表:

参数 描述
thread 线程句柄
返回 RT_EOK: 线程挂起成功,-RT_ERROR: 线程挂起失败,因为该线程的状态并不是就绪状态

注:一个线程尝试挂起另一个线程是一个非常危险的行为,因此RT-Thread对此函数有严格的使用限制:该函数只能使用来挂起当前线程(即自己挂起自己),不可以在线程A中尝试挂起线程B。而且在挂起线程自己后,需要立刻调用 rt_schedule() 函数进行手动的线程上下文切换。用户只需要了解该接口的作用即可,不建议在程序中使用该接口。该接口可以视为是内部接口。这是因为A线程在尝试挂起B线程时,A线程并不清楚B线程正在运行什么程序,一旦B线程正在使用影响、阻塞其他线程(如C线程)的内核对象(例如互斥量、信号量等)时,如果此时其他线程也在等待这个内核对象,那么A线程尝试挂起B线程的操作将会引发其他线程(如C线程)的饥饿,严重危及系统的实时性。有些地方会将其描述为死锁,实际上这种现象不是死锁,但是也没有比死锁好到哪去。

当线程调用 rt_thread_delay() 时,线程将主动挂起;当调用 rt_sem_take(),rt_mb_recv() 等函数时,资源不可使用也将导致线程挂起。处于挂起状态的线程,如果其等待的资源超时(超过其设定的等待时间),那么该线程将不再等待这些资源,并返回到就绪状态;或者,当其他线程释放掉该线程所等待的资源时,该线程也会返回到就绪状态。

2. 恢复线程

恢复线程就是让挂起的线程重新进入就绪状态,并将线程放入系统的就绪队列中;如果被恢复线程在所有就绪态线程中,位于最高优先级链表的第一位,那么系统将进行线程上下文的切换。线程恢复使用下面的函数接口:

rt_err_t rt_thread_resume (rt_thread_t thread);

线程恢复接口 rt_thread_resume() 的参数和返回值见下表:

参数 描述
thread 线程句柄
返回 RT_EOK: 线程恢复成功,-RT_ERROR: 线程恢复失败,因为该个线程的状态并不是 RT_THREAD_SUSPEND 状态

二、程序设计

在前一章节的基础上修改car_led.c、car_led.h和main.c三个文件即可,具体如下:

1. car_led.c

增加暂停标志、暂停设置接口,以及在线程中增加暂停执行代码

#include <rtthread.h>
#include <rtdevice.h>
#include "drv_common.h"

#define DBG_TAG "LED"
#define DBG_LVL DBG_LOG
#include <rtdbg.h>
#include <stdlib.h>
#include "car_led.h"
/* 定义左右转向灯的控制引脚 */
#define LedLeft GET_PIN(D, 8)
#define LedRight GET_PIN(D, 9)
#define LedOn(pin) rt_pin_write(pin, PIN_LOW)
#define LedOff(pin) rt_pin_write(pin, PIN_HIGH)

enum led_mode LedMod=LED_MODE_STOP;
void led_set_mode(enum led_mode m)
{
    LedMod = m;
}
/* 暂停运行标志变量,0表示运行,1表示暂停 */
static int stopFlag=0;
void led_thread_entry()
{
    rt_pin_mode(LedLeft, PIN_MODE_OUTPUT);
    rt_pin_mode(LedRight, PIN_MODE_OUTPUT);
while(1){
    /*判断是否暂停运行*/
        if(stopFlag)
        {
            rt_thread_suspend(rt_thread_self());//挂起线程,只能自已挂起自已
            rt_schedule();//使用suspend挂起线程后,需手动进行线程上下文切换
        }
        switch(LedMod)
        {
        case LED_MODE_STOP:
            LedOff(LedLeft);
            LedOff(LedRight);
            break;
        case LED_MODE_Double:
            LedOn(LedLeft);
            LedOn(LedRight);
            rt_thread_mdelay(500);
            LedOff(LedLeft);
            LedOff(LedRight);
            break;
        case LED_MODE_LEFT:
            LedOff(LedRight);
            LedOn(LedLeft);
            rt_thread_mdelay(250);
            LedOff(LedLeft);
            break;
        case LED_MODE_RIGHT:
            LedOff(LedLeft);
            LedOn(LedRight);
            rt_thread_mdelay(250);
            LedOff(LedRight);
            break;
        default:
            LOG_D("mode error\n");
        }
        rt_thread_mdelay(250);
    }
}
void ledmode(int argn, char *argv[])
{
    if(argn<2){
        LOG_W("ledmode #mode");
        return ;
    }
    led_set_mode(atoi(argv[1]));

}
void led_stop_flag(int i)//设置暂停标志的接口
{
    stopFlag=i;
}

/* 导出到 msh 命令列表中 */
MSH_CMD_EXPORT(ledmode, set led flash mode);

2.car_led.h

代码如下:

#ifndef APPLICATIONS_CAR_LED_H_
#define APPLICATIONS_CAR_LED_H_

/* 车灯闪烁模式定义 */
enum led_mode {
    LED_MODE_STOP=0, //停止闪烁
    LED_MODE_Double, //双闪
    LED_MODE_LEFT,   //左灯闪烁
    LED_MODE_RIGHT   //右灯闪烁
};
void led_thread_entry();               //线程入口函数声明
void led_set_mode(enum led_mode m);    //车灯闪烁模式设置声明
void led_stop_flag(int i); //接口声明,同时导出模块接口供其它模块使用

#endif /* APPLICATIONS_CAR_LED_H_ */

3. main.c

主要修改stop_led_thread()函数的实现,同时增加线程恢复函数,并把线程恢复函数导出到msh命令中,使我们可以通过终端来恢复线程。

#include <rtthread.h>
#define DBG_TAG "main"
#define DBG_LVL DBG_LOG
#include <rtdbg.h>
#include "car_led.h"    //包含LED控制模块头文件
#include "car_beep.h"   //包含蜂鸣器控制模块头文件

#define THREAD_STACK_SIZE   1024   //定义线程栈大小
#define THREAD_PRIORITY     20     //定义线程优先级
#define THREAD_TIMESLICE    10     //定义线程时间片

/* 栈首地址必须系统对齐 */
ALIGN(RT_ALIGN_SIZE)
static char beep_stack[THREAD_STACK_SIZE];  //定义栈空间
static struct rt_thread beepThread;    //静态方式定义beep线程控制块
rt_thread_t TidLed = RT_NULL;  //动态方式定义LED线程句柄

int main(void)
{
    int ret;

    /* 动态方式创建线程 */
    TidLed = rt_thread_create("LED", 
								led_thread_entry, 
								RT_NULL,
								THREAD_STACK_SIZE, 
								THREAD_PRIORITY, 
								THREAD_TIMESLICE);
    if (TidLed != RT_NULL)//判断线程是否成功创建
        rt_thread_startup(TidLed);//成功则启动线程
    else {//否则打印日志并即出
        LOG_D("can not create LED thread!");
        return -1;
    }

    /* 采用静态方式初始化线程 */
    ret = rt_thread_init(&beepThread,
                            "BEEP",
                            beep_thread_entry,
                            RT_NULL,
                            &beep_stack[0],
                            sizeof(beep_stack),
                            THREAD_PRIORITY,
                            THREAD_TIMESLICE);
    if (ret == RT_EOK) //判断线程是否成功创建
        rt_thread_startup(&beepThread); //成功则启动线程
    else { //否则打印日志并即出
        LOG_D("can not init beep thread!");
        return -1;
    }

    return RT_EOK;
}
void stop_led_thread()//暂停运行
{
     led_stop_flag(1);
}
void resume_led_thread()//恢复运行
{
    led_stop_flag(0);//先设置为运行
    rt_thread_resume(TidLed);//再恢复线程
    return;
}
/* 导出到 msh 命令列表中 */
MSH_CMD_EXPORT(resume_led_thread, resume led thread);//唤醒命令
MSH_CMD_EXPORT(stop_led_thread, stop led thread);

三、程序测试

(1)系统启动后,使用命令“ledmode 1”使能车灯双闪,观察到车灯闪烁。
【STM32&RT-Thread零基础入门】 6. 线程创建应用(线程挂起与恢复),STM32 RT-Thread操作系统入门,stm32,嵌入式硬件,单片机
(2)输入命令“stop_led_thread”命令,观察到车灯停止闪烁,说明线程已经被挂起。
【STM32&RT-Thread零基础入门】 6. 线程创建应用(线程挂起与恢复),STM32 RT-Thread操作系统入门,stm32,嵌入式硬件,单片机
(3)输入命令“resume_led_thread”命令,观察到车灯重新闪烁,说明线程被重新唤醒。
【STM32&RT-Thread零基础入门】 6. 线程创建应用(线程挂起与恢复),STM32 RT-Thread操作系统入门,stm32,嵌入式硬件,单片机
(4)输入命令“ps”命令,如图所示,观察到BEEP和LED两个线程都处理挂起状态,这主要是因为ps命令输出时,CPU正在运行tshell程序(命令是在tshell线程上下文件中运行的),而此时BEEP和LED两个线程因为执行rt_thread_mdelay()函数而被挂起。
【STM32&RT-Thread零基础入门】 6. 线程创建应用(线程挂起与恢复),STM32 RT-Thread操作系统入门,stm32,嵌入式硬件,单片机


总结

本章节学习线程的挂起与恢复的应用文章来源地址https://www.toymoban.com/news/detail-665323.html

到了这里,关于【STM32&RT-Thread零基础入门】 6. 线程创建应用(线程挂起与恢复)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【STM32&RT-Thread零基础入门】8. 基于 CubeMX 移植 RT-Thread Nano

    硬件:STM32F103ZET6、ST-LINK、usb转串口工具、4个LED灯、1个蜂鸣器、4个1k电阻、2个按键、面包板、杜邦线 利用RT_Thread操作系统实现三种不同的LED等闪烁 提示:以下是本篇文章正文内容,下面案例可供参考 cubemx配置参考教程: 基于 CubeMX 移植 RT-Thread Nano 后面程序所需的引脚 RT

    2024年02月09日
    浏览(48)
  • 【STM32&RT-Thread零基础入门】 3. PIN设备(GPIO)的使用

    硬件:STM32F103ZET6、ST-LINK、usb转串口工具、4个LED灯、1个蜂鸣器、4个1k电阻、2个按键、面包板、杜邦线 在嵌入式系统中,GPIO是最常用的一种设备,在RT-Thread操作系统中,把GPIO命名为PIN设备。 RT-Thread通过PIN设备对芯片的GPIO引脚进行管理,应用程序可以通过其提供的一组PIN设备

    2024年02月13日
    浏览(48)
  • STM32CubeMX+VSCODE+EIDE+RT-THREAD 工程创建

            Eide环境搭建暂且不表,后续补充。主要记录下Vscode环境下 创建Rt-thread工程的过程。分别介绍STM32CubeMX添加rtt支持包的方式和手动添加rtt kernel方式。STM32CubeMX生成工程的时候有\\\"坑\\\",防止下次忘记,方便渡一下有缘人,特此记录。         此工程以创建stm32f405为例

    2024年02月14日
    浏览(50)
  • RT-Thread:STM32实时时钟 RTC开启及应用

    说明: STM32F103/407系列基于 RT-Thread 系统的 RTC 开启及应用 应用流程介绍。 完成以上系统配置,编译无误情况下RTC 就已经开启了。 官方 API 查询地址:https://www.rt-thread.org/document/api/rtc_sample_8c-example.html#a3 1.设置日期:设置系统日期但不修改时间 2.设置时间:设置系统时间但不

    2024年01月17日
    浏览(62)
  • 使用RT-Thread Studio搭配STM32CubeMX新建RT-Thread项目

    STM32CubeMX下载 RT-Thread Studio下载 安装好RT-Thread Studio后,先打开RT-Thread SDK管理器确认有没有自己MCU需要的SDK包,直接安装好之后里面是有STM32F1系列的SDK包,其他的需要自己安装。 之后点击文件→新建→RT-Thread项目,根据自己需要配置好后点击完成就会生成RT-Thread项目。 新建项

    2024年02月11日
    浏览(52)
  • Rt-Thread 移植5--空闲线程和线程阻塞(KF32)

    src中定义idle.c clock.c 5.3.6 中断函数 irq.c main.c

    2024年02月06日
    浏览(42)
  • [嵌入式系统-32]:RT-Thread -17- 任务、进程、线程的区别

    目录 一、基本概念澄清 1.1 任务 1.2 进程 1.3 线程 1.4 比较 1.5 任务VS进程 1.6 进程 VS 线程 1.7 任务 进程 线程 发展历史 任务(Task): 进程(Process): 线程(Thread): 发展趋势: 二、不同操作系统中任务、进程、线程 2.1 Linux:没人任务,只有进程与线程 进程相关函数: 线程

    2024年02月21日
    浏览(45)
  • STM32 + RT-Thread + LwIp + DM9000

    开发板:STM32F103ZET6(战舰) RT-Thread:5.0.0 LwIp:2.1.2 网卡芯片:DM9000 编译环境:keil 我简单了解了一下,在嵌入式中,网络芯片的使用方式大致有三种,如下: (MCU + MAC + PHY) (MUC + MAC) —— PHY MCU —— (MAC + PHY) 注意: 我用括号里面的表示在同一块芯片中 移植 RT-Thread 不是此文

    2024年02月07日
    浏览(49)
  • RT-Thread入门笔记5-线程的时间片轮询调度

    优先级和时间片是线程的两个重要参数,优先级描述了线程竞争处理器资源的能力。 优先级和时间片 优先级 RT-Thread 最大支持 256 个优先级(数值越小的优先级越高,0 为最高优先级, 最低优先级预留给空闲线程);用户可以通过rt_config.h中的RT_THREAD_PRIORITY_MAX宏来修改最大支持

    2024年02月02日
    浏览(43)
  • RT-Thread STM32 GoKit V2.1 开发板BSP说明

    本文档为刘恒为 GoKit V2.1 开发板提供的 BSP (板级支持包) 说明。 主要内容如下: 开发板资源介绍 BSP 快速上手 进阶使用方法 通过阅读快速上手章节开发者可以快速地上手该 BSP,将 RT-Thread 运行在开发板上。在进阶使用指南章节,将会介绍更多高级功能,帮助开发者利用 RT-

    2024年02月04日
    浏览(41)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包